AuthorizationCodeProvider: Create никогда не вызывается, как мне сгенерировать код авторизации? - PullRequest
3 голосов
/ 17 апреля 2019

Я настраиваю свой собственный сервер 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 с (неправильным) параметром кода, и в отладчике я вижу, что мой AuthorizationCodeProvider вызов Receive выполнен.Конечно, успеха нет, потому что код, который я посылаю, - это «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, меня сразу отправляют на , который Ури.Я знаю, что это неправильно: меня нужно отправить на отдельную страницу входа.Я исправлю свой Web API позже, чтобы перенаправить на правильный Uri.

Суть моего вопроса заключается в следующем: я сейчас нахожусь в процессе реализации страницы входа, но я не знаю, как получитькод авторизации из моего WebAPI после того, как пользователь вошел в систему. (Я пропускаю часть согласия на данный момент и предполагаю, что, если пользователь вошел в систему, с ним все в порядке, я добавлю согласие позже.)

Я основываю свой поток на представленной здесь диаграмме https://docs.apigee.com/api-platform/security/oauth/oauth-v2-policy-authorization-code-grant-type

Я использую Thinktecture IdentityModel для создания страницы входа в контроллер MVC.Теперь мне нужно получить код авторизации из Web API в моем контроллере MVC.И после этого я могу перенаправить пользователя обратно к исходному клиенту (приложению), который запросил поток кода авторизации.

Чтобы получить код авторизации из моего веб-API, я вижу три метода в OAuth2Client Thinktecture:

  • CreateAuthorizeUrl
  • CreateCodeFlowUrl
  • RequestAuthorizationCodeAsync

Кажется, ни один из них не делает то, что я хочу.Как мне сделать так, чтобы мой 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);
    }

Я думаю, что он правильно настроен на стороне Web API.Я просто не знаю, как попасть в Create часть потока.Я надеюсь, что кто-то может помочь мне понять, что я не вижу.У меня где-то есть слепое пятно, я думаю ...

Как мне OAuth2Client получить мне код авторизации из моего WebAPI?

Я также , использую Почтальон для тестированиямой веб-API.Если кто-то может помочь мне получить URL-адрес в Web API 2.0, который возвращает код авторизации, я бы также принял это как ответ.Тогда я сам смогу написать код в MVC.

Edit

Хорошо, так что я думаю, что нашел часть моего слепого пятна.Во-первых, я пометил 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 для вошедшего в систему пользователя?

1 Ответ

0 голосов
/ 01 мая 2019

Итак, после некоторого поиска в Интернете, я добился определенного успеха, выполнив поиск по github.Очевидно, OAuthAuthorizationServerProvider предлагает AuthorizeEndpoint, и этот метод следует использовать для обоих: «Эй, вы не авторизованы, зайдите в систему!»а также для «Ааа, хорошо, ты крутой, вот код авторизации».Я ожидал, что OAuthAuthorizationServerProvider будет иметь два отдельных метода для этого, но это не так.Это объясняет, почему на github я нахожу некоторые проекты, которые реализуют AuthorizeEndpoint довольно своеобразным способом.Я принял это.Вот пример:

public override async Task AuthorizeEndpoint(OAuthAuthorizeEndpointContext context)
{
    if (context.Request.User != null && context.Request.User.Identity.IsAuthenticated)
    {
        var redirectUri = context.Request.Query["redirect_uri"];
        var clientId = context.Request.Query["client_id"];

        var authorizeCodeContext = new AuthenticationTokenCreateContext(
            context.OwinContext, 
            context.Options.AuthorizationCodeFormat,
            new AuthenticationTicket(
                (ClaimsIdentity)context.Request.User.Identity,
                new AuthenticationProperties(new Dictionary<string, string>
                {
                    {"client_id", clientId},
                    {"redirect_uri", redirectUri}
                })
            {
                IssuedUtc = DateTimeOffset.UtcNow,
                ExpiresUtc = DateTimeOffset.UtcNow.Add(context.Options.AuthorizationCodeExpireTimeSpan)
            }));

        await context.Options.AuthorizationCodeProvider.CreateAsync(authorizeCodeContext);

        context.Response.Redirect(redirectUri + "?code=" + Uri.EscapeDataString(authorizeCodeContext.Token));
    }
    else
    {
        context.Response.Redirect("/account/login?returnUrl=" + Uri.EscapeDataString(context.Request.Uri.ToString()));
    }
    context.RequestCompleted();
}

Источник: https://github.com/wj60387/WebApiOAUthBase/blob/master/OwinWebApiBase/WebApiOwinBase/Providers/OAuthServerProvider.cs

Что касается моих оставшихся трех вопросов:

  1. Прямо сейчас любой может запросить код авторизации,client_id игнорируется.ValidateClientAuthentication, очевидно, не используется как часть AuthorizeEndpoint.Как получить ClientId в AuthorizeEndpoint?

Ответ: Вы должны реализовать `ValidateClientAuthentication '.

Код авторизации не связан с клиентом.Любой, кто перехватывает код, может использовать его.Как получить ClientId в AuthorizationCodeProvider.Create, чтобы я мог сохранить его с кодом?

Ответ: OAuthAuthorizationServerProvider позаботится об этом.Пока вы указали в заявке «client_id», он будет проверять, является ли клиент, запрашивающий токен доступа для кода авторизации, одинаковым.

Код авторизации вообще не связан с пользователем, это пустой ClaimsIdentity.Как поместить страницу входа пользователя между и в AuthorizeEndpoint для получения ClaimsIdentity для вошедшего в систему пользователя?

Ответ: Вы создаете отдельную страницу входа.Для этого нужно войти в систему. Если ваш WebAPI использует аутентификацию на основе файлов cookie, вы можете просто перенаправить пользователя на AuthorizeEndpoint снова.Если вы используете токены доступа, ваша страница входа в систему должна сделать запрос к AuthorizeEndpoint с токеном доступа для получения кода авторизации.(Не передавайте токен доступа третьей стороне. Ваша страница входа запрашивает код авторизации и отправляет его обратно.) Другими словами, если вы используете токены доступа, тогда в этом потоке участвуют два клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...