При создании нового 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() : <strong>string.Empty</strong>;
}
}
Идем дальше. Класс VkAuthenticationOptions
:
class 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");
// ...
}
И наступает счастье.
Все и сразу мужно скачать вот здесь.