Реализация авторизации с помощью ВКонтакте используя Microsoft.Owin.Security

.NET Вконтакте Owin Katana C#

При создании нового Web проекта в Visual Studio 2013 нам предлагается готовый шаблон сайта с уже реализованной системой авторизации с помощью различных популярных в мире сервисов авторизации. Среди них есть Microsoft Account, Facebook, Twitter и Google. Это чудесное API называется Katana project.

Однако поддержки ВКонтакте "из коробки" нет. Оно и понятно - API писали люди, которые скорее всего ничего про ВКонтакте не знают.

Как бы многие IT-шники не плевались, а на территории СНГ "вконтактик" очень популярен и отказывать сабе в интеграции с ним только потому, что он кому-то не нравится - глупо. Однако, я повторюсь, "из коробки" его нет.

Ну, нет так нет. Напишем сами.

Начнем мы с того, с чего началось создание самого ВКонтакта. А именно с копирования Facebook'а. В нашем случае мы возьмем реализацию для Facebook'а и адаптируем ее для ВКонтакта.

Забираем исходники Катаны:

git clone https://git01.codeplex.com/katanaproject

И смотрим в папку Microsoft.Owin.Security.Facebook.

Бессовестно копируем ее, попутно заменяя все слова Facebook в именах классов на Vk. Понятно, что одним переименованием классов дело не закончится. Начинаем менять код.

В классе Constants меняем поле DefaultAuthenticationType

public const string DefaultAuthenticationType = "ВКонтакте";

Класс VkAuthenticatedContext

    public class VkAuthenticatedContext : BaseContext
    {
        public VkAuthenticatedContext(IOwinContext context, JObject user, string accessToken)
            : base(context)
        {
            User = user;
            AccessToken = accessToken;

            Id = TryGetValue(user, "uid");
            UserName = (TryGetValue(user, "first_name") + " " + TryGetValue(user, "last_name")).Trim();
        }

        public JObject User { get; private set; }
        public string AccessToken { get; private set; }

        public string Id { get; private set; }
        public string UserName { get; private set; }

        public ClaimsIdentity Identity { get; set; }
        public AuthenticationProperties Properties { get; set; }

        private static string TryGetValue(JObject user, string propertyName)
        {
            JToken value;
            return user.TryGetValue(propertyName, out value) ? value.ToString() : string.Empty;
        }
    }

Жирным текстом выделены изменения.

Идем дальше. Класс VkAuthenticationOptions:

    public VkAuthenticationOptions()
        : base(Constants.DefaultAuthenticationType)
    {
        Caption = Constants.DefaultAuthenticationType;
        ReturnEndpointPath = "/signin-vk";
        AuthenticationMode = AuthenticationMode.Passive;
        Scope = new List<string>();
        BackchannelTimeout = TimeSpan.FromSeconds(60);
    }

Меняем точку возврата после авторизации. На этот URL будет отправлен код, который нужен для получения access_token'а.

Теперь самое интересное - класс VkAuthenticationHandler

В методе:

protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()

Меняем следующий фрагмент:

string tokenEndpoint = "https://oauth.vk.com/access_token";

string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.ReturnEndpointPath;

string tokenRequest = 
    "?client_id=" + Uri.EscapeDataString(Options.AppId) +
    "&client_secret=" + Uri.EscapeDataString(Options.AppSecret) +
    "&code=" + Uri.EscapeDataString(code) +
    "&redirect_uri=" + Uri.EscapeDataString(redirectUri);

HttpResponseMessage tokenResponse = await _httpClient.GetAsync(tokenEndpoint + tokenRequest, Request.CallCancelled);
tokenResponse.EnsureSuccessStatusCode(); string text = await tokenResponse.Content.ReadAsStringAsync(); var form = JsonConvert.DeserializeObject<Dictionary<string, object>>(text); var accessToken = (string)form["access_token"]; var userId = (long)form["user_id"]; string graphApiEndpoint = "https://api.vk.com/method/users.get" + "?user_id=" + userId + "&fields=" + "&name_case=Nom" + "&access_token=" + Uri.EscapeDataString(accessToken); HttpResponseMessage graphResponse = await _httpClient.GetAsync(graphApiEndpoint, Request.CallCancelled); graphResponse.EnsureSuccessStatusCode(); text = await graphResponse.Content.ReadAsStringAsync(); JObject data = JObject.Parse(text); var user = (JObject) data["response"].First; var context = new VkAuthenticatedContext(Context, user, accessToken);

а в методе:

protected override Task ApplyResponseChallengeAsync()

вот такой фрагмент:

string authorizationEndpoint =
    "https://oauth.vk.com/authorize" +
    "?client_id=" + Uri.EscapeDataString(Options.AppId ?? string.Empty) +
    "&scope=" + Uri.EscapeDataString(scope) +
    "&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
    "&response_type=code" +
    "&state=" + Uri.EscapeDataString(state);

И почти финал. В классе VkAuthenticationExtensions меняем имя метода UseFacebookAuthentication на UseVkAuthentication.

Теперь финал. Собираем и подключаем к проекту:

public void Configuration(IAppBuilder app)
{
    // ...
    app.UseVkAuthentication(
        appId: "999999",
        appSecret: "z5ZkSw1bkQV88YMRYA7vg");
// ... }

И наступает счастье.

Все и сразу мужно скачать вот здесь.

Оставить комментарий могут только зарегистрированные пользователи.

Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.