Я настраиваю свой собственный сервер OAuth2. До сих пор я успешно реализовал GrantResourceOwnerCredentials
в своей реализации OAuthAuthorizationServerProvider
. Теперь, поскольку я разрабатываю приложение для нашего бизнеса, я хочу реализовать грант кода авторизации OAuth2.
Я пытался следовать указаниям здесь https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server, но в моей реализации я не нашел как достучаться до Create
звонка AuthorizationCodeProvider
(которую поставил в OAuthAuthorizationServerOptions
).
Я кратко проверил, работает ли доступ к TokenEndpointPath
с (неправильным) параметром кода, и в отладчике я вижу, что вызов Receive
моего AuthorizationCodeProvider
срабатывает. Конечно, успеха нет, потому что код, который я отправляю, является «sometestcode», а не реальным, но код срабатывает, а это значит, что я на правильном пути.
Вот что у меня есть до сих пор:
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (OAuthRepository.GetClient(context.ClientId) != null)
{
var expectedRootUri = new Uri(context.Request.Uri, "/");
if (context.RedirectUri.StartsWith(expectedRootUri.AbsoluteUri))
{
context.Validated();
return Task.FromResult<object>(null);
}
}
context.Rejected();
return Task.FromResult<object>(null);
}
public override Task AuthorizeEndpoint(OAuthAuthorizeEndpointContext context)
{
// I know this is wrong but it's just a start and not the focus of this SO question.
context.Response.Redirect(context.AuthorizeRequest.RedirectUri);
context.RequestCompleted();
return Task.FromResult<object>(null);
}
public override Task GrantAuthorizationCode(OAuthGrantAuthorizationCodeContext context)
{
// Needs additional checks, not the focus of my question either
var newTicket = new AuthenticationTicket(context.Ticket.Identity, context.Ticket.Properties);
context.Validated(newTicket);
return Task.FromResult<object>(null);
}
Теперь, когда я звоню своему AuthorizeEndpointPath
с помощью redirect_uri
, меня немедленно отправляют к этому Ури. Я знаю, что это неправильно: меня должны отправить на отдельную страницу входа. Позже я исправлю свой веб-API, чтобы перенаправить на правильный Uri.
Суть моего вопроса заключается в следующем: сейчас я нахожусь в процессе реализации страницы входа, но я не знаю, как получить код авторизации из моего WebAPI после того, как пользователь вошел в систему. (Я пропускаю часть согласия для теперь и предположим, что если пользователь вошел в систему, с ним все в порядке, я добавлю согласие позже.)
Я основываю свой поток на схеме, опубликованной здесь https://docs.apigee.com/api-platform/security/oauth/oauth-v2-policy-authorization-code-grant-type
Я использую Thinktecture IdentityModel для создания страницы входа в контроллер MVC. Теперь мне нужно получить код авторизации из веб-API в моем контроллере MVC. И после этого я могу перенаправить пользователя обратно к исходному клиенту (приложению), которое запросило поток кода авторизации.
Чтобы получить код авторизации из моего веб-API, я вижу три метода в OAuth2Client Thinktecture:
- CreateAuthorizeUrl
- CreateCodeFlowUrl
- реквестауториатионатионкодеасинк
Кажется, ни один из них не делает то, что я хочу. Как мне поступить, чтобы мой WebAPI вызывался для генерации кода?
[HttpGet]
[ImportModelStateFromTempData]
public ActionResult Authorize(string clientId, string returnUrl, string responseType)
{
AuthorizeViewModel viewModel = new AuthorizeViewModel();
...
...
...
return View(viewModel);
}
[HttpPost]
[ExportModelStateToTempData]
public async Task<ActionResult> Authorize(AuthorizeViewModel viewModel)
{
// NOTE: This is in MVC and is postback from *.cshtml View.
OAuth2Client.?????? // <=== How to obtain authorization code from WebAPI?
...
return Redirect(returnUrl);
}
Я думаю, что правильно настроил его на стороне веб-API. Я просто не знаю, как попасть в Create
часть потока. Я надеюсь, что кто-то может помочь мне понять, чего я не вижу. У меня где-то слепое пятно, я думаю...
Как заставить OAuth2Client получить код авторизации из моего WebAPI?
Я также использую Postman для тестирования своего веб-API. Если кто-нибудь может помочь мне получить URL-адрес в Web API 2.0, который возвращает код авторизации, я также приму это как ответ. Тогда я смогу сам написать код в MVC.
Редактировать
Итак, я думаю, что нашел часть своего слепого пятна. Во-первых, я отметил «AuthorizeEndpoint» как «не в центре внимания этого вопроса SO», но это было большой ошибкой.
Когда я адаптирую AuthorizeEndpoint следующим образом:
public override Task AuthorizeEndpoint(OAuthAuthorizeEndpointContext context)
{
System.Security.Claims.ClaimsIdentity ci = new System.Security.Claims.ClaimsIdentity("Bearer");
context.OwinContext.Authentication.SignIn(ci);
context.RequestCompleted();
return Task.FromResult<object>(null);
}
И если я адаптирую свою реализацию AuthorizationCodeProvider.Create
так:
public void Create(AuthenticationTokenCreateContext context)
{
context.Ticket.Properties.IssuedUtc = DateTime.UtcNow;
context.Ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddSeconds(60);
// Some random Guid
context.SetToken(Guid.NewGuid().ToString("n"));
}
Любой вызов /authorize
перенаправляется на redirect_uri
с параметром запроса code=<THE_RANDOM_GUID>
! :D
Очевидно, что эта реализация не там, где должна быть, поэтому мой вопрос еще не решен. Оставшиеся проблемы:
- Прямо сейчас любой может запросить код авторизации, client_id игнорируется.
ValidateClientAuthentication
, по-видимому, не пострадал как частьAuthorizeEndpoint
. Как получить ClientId в AuthorizeEndpoint? - Код авторизации не привязан к клиенту. Любой, кто перехватит код, сможет его использовать. Как мне получить ClientId в
AuthorizationCodeProvider.Create
, чтобы сохранить его вместе с кодом? - Код авторизации вообще не привязан к пользователю, это пустой ClaimsIdentity. Как поместить страницу входа пользователя между ними, а в AuthorizeEndpoint получить
ClaimsIdentity
для вошедшего в систему пользователя?