Проверка токенов, выданных AspNet.Security.OpenIdConnect.Server (ASP.NET vNext)

Я использую Visual Studio 2015 Enterprise и ASP.NET vNext Beta8 для создания конечной точки, которая выдает и использует токены JWT. Первоначально я подошел к этому, генерируя токены сам, как описаноВот, Позже полезностатья @Pinpoint показал, что AspNet.Security.OpenIdConnect.Server (a.k.a. OIDC) можно настроить для выдачи и использования токенов для меня.

Поэтому я следовал этим инструкциям, поднял конечную точку и отправил сообщение в формате x-www-form-urlencoded отпочтальон Я получаю обратно законный токен:

{
  "token_type": "bearer",
  "access_token": "eyJ0eXAiO....",
  "expires_in": "3599"
}

Это здорово, но и там, где я застреваю. Теперь, как мне аннотировать действие контроллера, чтобы оно требовало этот токен?

Я думал, что все, что мне нужно сделать, это украсить свой метод контроллера с помощью [Authorize ("Bearer")], добавить схему аутентификации:

        services.AddAuthorization
        (
            options => 
            {
                options.AddPolicy
                (
                    JwtBearerDefaults.AuthenticationScheme, 
                    builder => 
                    {
                        builder.
                        AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
                        RequireAuthenticatedUser().
                        Build();
                    } 
                );
            }
        );

А затем вызовите действие моего контроллера с заголовком «Authorare bearer eyJ0eXAiO ....», как я делал в своем предыдущем примере. К сожалению, кажется, что весь этот подход делает исключение:

Произошло необработанное исключение при обработке запроса.

SocketException: не может быть установлено соединение, потому что целевая машина активно отказалась от него 127.0.0.1:50000

WebException: невозможно подключиться к удаленному серверу

HttpRequestException: произошла ошибка при отправке запроса.

IOException: IDX10804: невозможно получить документ из: 'HTTP: // локальный: 50000 / .well известный / конфигурация OpenID». Microsoft.IdentityModel.Logging.LogHelper.Throw (Строковое сообщение, Тип exceptionType, EventLevel logLevel, Исключение innerException)

InvalidOperationException: IDX10803: невозможно получить конфигурацию из: 'HTTP: // локальный: 50000 / .well известный / конфигурация OpenID». Внутреннее исключение: 'IDX10804: невозможно получить документ из:'HTTP: // локальный: 50000 / .well известный / конфигурация OpenID''.


Рассмотрите следующие шаги для воспроизведения (но, пожалуйста, не считайте этот производственно-достойный код):

Примените инструментарий ASP.NET Beta8, как описаноВот

Откройте Visual Studio Enterprise 2015 и создайте новый проект шаблона веб-API ASP.NET 5 Preview.

Изменить проект.json

{
"webroot": "wwwroot",
"версия": "1.0.0- *",

"зависимости": {
«Microsoft.AspNet.IISPlatformHandler»: «1.0.0-бета8»,
«Microsoft.AspNet.Mvc»: «6.0.0-бета8»,
«Microsoft.AspNet.Server.Kestrel»: «1.0.0-бета8»,
«Microsoft.AspNet.Authentication.JwtBearer»: «1.0.0-бета8»,
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta3",
«Microsoft.AspNet.Authentication.OpenIdConnect»: «1.0.0-бета8»,
«Microsoft.Framework.ConfigurationModel.Json»: «1.0.0-бета4»,
«Microsoft.AspNet.Diagnostics»: «1.0.0-бета8»
},

"команды": {
"Интернет": "Microsoft.AspNet.Server.Kestrel"
},

"рамки": {
"dnx451": {}
},

"исключить": [
"Wwwroot",
"node_modules"
],
"publishExclude": [
".user»,
"
.vspscc»
]
}

Измените файл Startup.cs следующим образом (это любезно предоставлено исходной статьей @ Pinpoint; я удалил комментарии и добавил фрагмент AddAuthorization):

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthorization
        (
            options => 
            {
                options.AddPolicy
                (
                    JwtBearerDefaults.AuthenticationScheme, 
                    builder => 
                    {
                        builder.
                        AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).
                        RequireAuthenticatedUser().
                        Build();
                    } 
                );
            }
        );
        services.AddAuthentication();
        services.AddCaching();
        services.AddMvc();
        services.AddOptions();
    }

    // Configure is called after ConfigureServices is called.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<AppSettings> appSettings)
    {
        app.UseDeveloperExceptionPage();

        // Add a new middleware validating access tokens issued by the OIDC server.
        app.UseJwtBearerAuthentication(options => {
            options.AutomaticAuthentication = true;
            options.Audience = "http://localhost:50000/";
            options.Authority = "http://localhost:50000/";
            options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>
            (
                metadataAddress : options.Authority + ".well-known/openid-configuration",
                configRetriever : new OpenIdConnectConfigurationRetriever(),
                docRetriever    : new HttpDocumentRetriever { RequireHttps = false }
            );
        });

        // Add a new middleware issuing tokens.
        app.UseOpenIdConnectServer
        (
            configuration => 
            {
                configuration.Options.TokenEndpointPath= "/authorization/v1";
                configuration.Options.AllowInsecureHttp = true;
                configuration.Provider = new OpenIdConnectServerProvider {

                    OnValidateClientAuthentication = context => 
                    {
                        context.Skipped();
                        return Task.FromResult<object>(null);
                    },

                    OnGrantResourceOwnerCredentials = context => 
                    {
                        var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);
                        identity.AddClaim( new Claim(ClaimTypes.NameIdentifier, "todo")  );
                        identity.AddClaim( new Claim("urn:customclaim", "value", "token id_token"));
                        context.Validated(new ClaimsPrincipal(identity));
                        return Task.FromResult<object>(null);
                    }
                };
            }
        );

        app.UseMvc();
    }
}
Измените wizarded ValuesController.cs, чтобы указать атрибут Authorize:
[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET: api/values
    [Authorize("Bearer")] 
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

Запустите проект и получите токен, используяпочтальон, Для получения токена используйте POST x-www-form-urlencoded с «grant_type» из «password», «username» что-нибудь, «password» что-нибудь и «resource» адресом конечной точки API. Например, мой конкретный URLHTTP: // локальный: 37734 / разрешение / v1.

Скопируйте токен в кодировке Base64, затем используйте токен для вызова контроллера значений мастера, используяпочтальон, Для использования токена создайте GET с заголовками Content-Type application / json и носителем авторизации eyJ0eXAiO .... (ваш токен). Мой конкретный URLHTTP: // локальный: 37734 / API / значения.

Соблюдайте исключение, упомянутое ранее.

Если подход [Authorize ("Bearer")], который я пытаюсь описать выше, является неправильным, я был бы очень признателен, если бы кто-нибудь помог мне разобраться в передовых методах получения токена JWT с помощью OIDC.

Спасибо.

Ответы на вопрос(1)

Ваш ответ на вопрос