Сервер OpenID Connect. Создание токена доступа на основе стороннего токена (социальный вход)

Я реализовал сервер OpenID Connect, который генерирует токены доступа для мобильного клиента на основе имени пользователя / пароля с использованием OpenIddict. Моей следующей целью было предоставить возможность генерировать токен доступа с использованием сторонних токенов (например, для входа в социальную сеть), и я начал с интеграции с токеном Google, но застрял, так как не могу найти никаких примеров / информации о том, как это сделать.

Единственная идея, которая у меня сейчас есть, - это сделать запрос к конечной точке "/connect/token" и отправить токен Google в параметре "code", например, в формате "google:", а затем переопределить метод OpenIdConnectServerProvider.DeserializeAuthorizationCode:

Вызывается при получении кода авторизации. Приложение может использовать этот контекст для десериализации кода с использованием пользовательского формата и для пропуска логики по умолчанию, используя

Итак, я создал собственный CustomProvider класс на основе OpenIddictProvider зарегистрировал это

services.AddOpenIddict<ApplicationUser, ApplicationRole, ApplicationDbContext, int>()
    .Configure(builder =>
    { builder.Provider = new CustomProvider(sp.GetRequiredService<SignInService>()); }

и переопределить DeserializeAuthorizationCode метод:

public override async Task DeserializeAuthorizationCode(DeserializeAuthorizationCodeContext context)
{
    string code = context.Request.Code;
    if (code.StartsWith("google:"))
    {
        string token = code.Replace("google:", "");
        var principal = new GoogleTokenValidator().ValidateToken(token, null).Result;
        var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), "Bearer");
        ticket.SetPresenters(context.Request.ClientId);
        context.Ticket = ticket;

        context.Ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddDays(1);
        context.HandleResponse();

        await _signInService.Login(principal);

        return; 
    }
    else
    {
        base.DeserializeAuthorizationCode(context);
    }
} 

где GoogleTokenValidator является пользовательским классом для обработки токенов Google (он обращается к конечной точке информации о пользователе Google и генерирует ClaimsPrincipal), основанный на "вставленном" коде из класса GoogleHandler в репозитории aspnet/Security.

В целом это работает с некоторыми дополнительными взломами, но у меня есть сильное чувство, что изобретать велосипед...

1 ответ

Решение

В целом это работает с некоторыми дополнительными взломами, но у меня есть сильное чувство, что изобретать велосипед...

Вы не только заново изобретаете колесо, но и реализуете что-то совершенно нестандартное, которое не поддерживается (вообще) OpenIddict.

Вот подход, который я рекомендую (который мы используем в примере сервера MVC):

  • Клиентское приложение OAuth2/OpenID Connect перенаправляет пользовательский агент на ваш контроллер авторизации (вы можете взглянуть на этот контроллер для примера).

  • OpenIddict проверит запрос авторизации и позволит вашему контроллеру быть вызванным, если он полностью действителен.

  • Если пользователь еще не вошел в систему, ваш контроллер авторизации перенаправит пользователя на конечную точку входа в систему, предоставленную AccountController, На этом этапе вы можете предложить локальную аутентификацию (например, с использованием пары имя пользователя / пароль) или аутентификацию Google (для этого вы можете использовать промежуточное ПО аутентификации Google). Вы даже можете предложить 2-FA как часть этого процесса входа в систему.

  • Как только пользователь вошел в систему (например, после процесса регистрации и / или внешней ассоциации аутентификации), его / ее браузер перенаправляется обратно в конечную точку авторизации, где форма согласия, указывающая, что он / она собирается позволить вашему приложению JS получить доступ к его личные данные от его / ее имени отображается.

  • Когда пользователь разрешает вашему клиентскому приложению получить доступ к своим данным, запрос обрабатывается вашим контроллером авторизации, который вызывает SignInAsync сообщить OpenIddict, что код авторизации / токен доступа должен быть возвращен вашему приложению.

Другие вопросы по тегам