"Сообщение": "В этом запросе отказано в авторизации". OWIN промежуточное ПО
Я добавил аутентификацию на основе токенов в свое промежуточное ПО OWIN и могу генерировать токен. Но при использовании токена для вызова API с атрибутом Authorize я всегда получаю "Авторизация была отклонена для этого запроса". Работает нормально, хотя без атрибута Authorize. Вот мой startup.cs и метод контроллера. Есть мысли, что не так?
startup.cs
public void Configuration(IAppBuilder app)
{
var issuer = ConfigurationManager.AppSettings["issuer"];
var secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["secret"]);
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new SimpleAuthProvider(),
AccessTokenFormat = new JwtFormat(issuer)
});
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { "*" },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
}
});
container = BuildDI();
var config = new HttpConfiguration();
config.Formatters.XmlFormatter.UseXmlSerializer = true;
config.MapHttpAttributeRoutes();
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ExternalBearer));
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseCors(CorsOptions.AllowAll);
app.UseSerilogRequestContext("RequestId");
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
RegisterShutdownCallback(app, container);
}
public class SimpleAuthProvider: OAuthAuthorizationServerProvider
{
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (context.UserName != context.Password)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
context.Rejected();
return Task.FromResult<object>(null);
}
var ticket = new AuthenticationTicket(SetClaimsIdentity(context), new AuthenticationProperties());
context.Validated(ticket);
return Task.FromResult<object>(null);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult<object>(null);
}
private static ClaimsIdentity SetClaimsIdentity(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(DefaultAuthenticationTypes.ExternalBearer);
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
return identity;
}
}
Метод Контроллера API:
[HttpGet]
[Route("sampleroute")]
[Authorize]
public async Task<HttpResponseMessage> GetSamples(string search)
{
try
{
HttpResponseMessage response;
using (HttpClient client = new HttpClient(Common.CreateHttpClientHandler()))
{
response = await client.GetAsync("test url");
}
var result = response.Content.ReadAsStringAsync().Result;
Samples[] sampleArray = JsonConvert.DeserializeObject<Samples[]>(result);
var filteredSamples = sampleArray .ToList().Where(y => y.NY_SampleName.ToUpper().Contains(search.ToUpper())).Select(n=>n);
log.Information("<==========Ended==========>");
return Request.CreateResponse(HttpStatusCode.OK,filteredSamples);
}
catch (Exception ex)
{
log.Error($"Error occured while pulling the Samples: {ex.ToString()}");
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.ToString());
}
}
2 ответа
Это, вероятно, проблема с разрешенной аудиторией. Вот
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
...
AllowedAudiences = new[] { "*" },
...
}
Вы устанавливаете разрешенную аудиторию. Жетоны aud
претензия будет проверена по списку AllowedAudiences
, Но вы никогда не добавляете аудиторию к токену.
В нашем проекте я использовал CustomJwtFormat, основанный на коде, показанном на http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/
Токен будет сгенерирован с вызовом
var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);
второй параметр отвечает за aud
претензия в JWT:
С https://msdn.microsoft.com/en-us/library/dn451037(v=vs.114).aspx:
Тип аудитории: System.String
Если это значение не равно NULL, будет добавлено утверждение { aud, 'аудитория' }.
После настройки aud
Заявка в токене авторизации должна работать нормально.
Из того, что я понял, нужно добавить заголовок: Авторизация: "Токен" на предъявителя. Если вы не изменили реализацию запроса авторизации по умолчанию, выполните следующие действия:
Зарегистрировать пользователя в конечной точке:
/api/Account/Register
- Отправьте в / токен следующие элементы:
- grant_type: пароль
- username: "имя пользователя, которое вы зарегистрировали"
- пароль: "пароль, который вы зарегистрировали для пользователя"
- Вы получите токен в ответе
Скопируйте этот токен и создайте запрос для метода, который вы защищаете с помощью фильтра [Authorize] типа:
Authorization: Bearer "the_token_you_copied_earlier"
Само собой разумеется, это может быть довольно легко для вас, если вы используете Postman или Fiddler для создания и получения запросов, потому что он показывает вам, как все работает.