Last active
December 11, 2015 05:58
-
-
Save shvydky/4556009 to your computer and use it in GitHub Desktop.
VKontakte OAuth client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using DotNetOpenAuth.AspNet.Clients; | |
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Linq; | |
using System.Net; | |
using System.Runtime.Serialization; | |
using System.Runtime.Serialization.Json; | |
using System.Web; | |
namespace Breeze.AspNet.Security.OAuth { | |
public class VKontakteOAuthProvider : OAuth2Client { | |
string appId; | |
string appSecret; | |
public VKontakteOAuthProvider(string appId, string appSecret) : base("vkontakte") { | |
if (String.IsNullOrEmpty(appId)) throw new ArgumentNullException("appId"); | |
if (String.IsNullOrEmpty(appSecret)) throw new ArgumentNullException("appSecret"); | |
this.appId = appId; | |
this.appSecret = appSecret; | |
} | |
protected override Uri GetServiceLoginUrl(Uri returnUrl) { | |
if (returnUrl == null) throw new ArgumentNullException("returnUrl"); | |
UriBuilder builder = new UriBuilder("https://oauth.vk.com/authorize"); | |
var args = new Dictionary<string, string>() { | |
{"client_id", appId}, | |
{"redirect_uri", NormalizeHexEncoding(returnUrl.AbsoluteUri)}, | |
{"display", "page"}, | |
{"response_type", "code"} | |
}; | |
builder.AppendQueryArgs(args); | |
return builder.Uri; | |
} | |
protected override IDictionary<string, string> GetUserData(string accessToken) { | |
if (accessToken == null) throw new ArgumentNullException("accessToken"); | |
var data = HttpContext.Current.Session["VKontakteOAuthProvider.Token"] as VKontakteTokenResponse; | |
if (data == null || data.AccessToken != accessToken) | |
return null; | |
var res = new Dictionary<string, string>(); | |
res.Add("id", data.UserId.ToString()); | |
UriBuilder builder = new UriBuilder("https://api.vk.com/method/users.get"); | |
Dictionary<string, string> args = new Dictionary<string, string>(); | |
args.Add("uids", data.UserId.ToString()); | |
args.Add("fields", "uid,first_name,last_name,nickname,sex,bdate"); | |
args.Add("access_token", accessToken); | |
builder.AppendQueryArgs(args); | |
using (WebClient client = new WebClient()) { | |
using (var stream = client.OpenRead(builder.Uri)) { | |
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(VKontakteDataResponse)); | |
var info = (VKontakteDataResponse)serializer.ReadObject(stream); | |
if (info.Items != null && info.Items.Count() > 0) { | |
var item = info.Items[0]; | |
res.AddItemIfNotEmpty("username", item.Username); | |
res.AddItemIfNotEmpty("name", (((item.FirstName ?? "") + " " + (item.LastName ?? "")).Trim())); | |
res.AddItemIfNotEmpty("birthday", item.Birthdate); | |
res.AddItemIfNotEmpty("gender", item.Sex); | |
} | |
} | |
} | |
return res; | |
} | |
protected override string QueryAccessToken(Uri returnUrl, string authorizationCode) { | |
UriBuilder builder = new UriBuilder("https://oauth.vk.com/access_token"); | |
Dictionary<string, string> args = new Dictionary<string, string>(); | |
args.Add("client_id", this.appId); | |
args.Add("redirect_uri", NormalizeHexEncoding(returnUrl.AbsoluteUri)); | |
args.Add("client_secret", this.appSecret); | |
args.Add("code", authorizationCode); | |
builder.AppendQueryArgs(args); | |
using (WebClient client = new WebClient()) { | |
using (var stream = client.OpenRead(builder.Uri)) { | |
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(VKontakteTokenResponse)); | |
var data = (VKontakteTokenResponse)serializer.ReadObject(stream); | |
HttpContext.Current.Session["VKontakteOAuthProvider.Token"] = data; | |
return data.AccessToken; | |
} | |
} | |
} | |
private static string NormalizeHexEncoding(string url) { | |
char[] chArray = url.ToCharArray(); | |
for (int i = 0; i < (chArray.Length - 2); i++) { | |
if (chArray[i] == '%') { | |
chArray[i + 1] = char.ToUpperInvariant(chArray[i + 1]); | |
chArray[i + 2] = char.ToUpperInvariant(chArray[i + 2]); | |
i += 2; | |
} | |
} | |
return new string(chArray); | |
} | |
} | |
[DataContract, EditorBrowsable(EditorBrowsableState.Never)] | |
internal class VKontakteTokenResponse { | |
[DataMember(Name = "access_token")] | |
public string AccessToken { get; set; } | |
[DataMember(Name = "user_id")] | |
public long UserId { get; set; } | |
[DataMember(Name = "expires_in")] | |
public long ExpiresIn { get; set; } | |
} | |
[DataContract, EditorBrowsable(EditorBrowsableState.Never)] | |
internal class VKontakteDataResponse { | |
[DataMember(Name = "response")] | |
public VKontakteDataItem[] Items { get; set; } | |
} | |
[DataContract, EditorBrowsable(EditorBrowsableState.Never)] | |
internal class VKontakteDataItem { | |
[DataMember(Name = "uid")] | |
public long UserId { get; set; } | |
[DataMember(Name = "sex")] | |
public string Sex { get; set; } | |
[DataMember(Name = "nickname")] | |
public string Username { get; set; } | |
[DataMember(Name = "first_name")] | |
public string FirstName { get; set; } | |
[DataMember(Name = "last_name")] | |
public string LastName { get; set; } | |
[DataMember(Name = "bdate")] | |
public string Birthdate { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Web; | |
namespace Breeze.AspNet.Security.OAuth { | |
public static class Helpers { | |
static string[] UriRfc3986CharsToEscape = new string[] { "!", "*", "'", "(", ")" }; | |
public static IDictionary<string, string> ParseJSON(this string str) { | |
return null; | |
} | |
public static void AppendQueryArgs(this UriBuilder builder, IEnumerable<KeyValuePair<string, string>> args) { | |
if (builder == null) throw new ArgumentNullException("builder"); | |
if ((args != null) && (args.Count<KeyValuePair<string, string>>() > 0)) { | |
StringBuilder builder2 = new StringBuilder(50 + (args.Count<KeyValuePair<string, string>>() * 10)); | |
if (!string.IsNullOrEmpty(builder.Query)) { | |
builder2.Append(builder.Query.Substring(1)); | |
builder2.Append('&'); | |
} | |
builder2.Append(CreateQueryString(args)); | |
builder.Query = builder2.ToString(); | |
} | |
} | |
public static string CreateQueryString(IEnumerable<KeyValuePair<string, string>> args) { | |
if (args == null) throw new ArgumentNullException("args"); | |
if (!args.Any<KeyValuePair<string, string>>()) { | |
return string.Empty; | |
} | |
StringBuilder builder = new StringBuilder(args.Count<KeyValuePair<string, string>>() * 10); | |
foreach (KeyValuePair<string, string> pair in args) { | |
if (string.IsNullOrEmpty(pair.Key)) | |
throw new ArgumentException("UnexpectedNullOrEmptyKey"); | |
if (pair.Value == null) | |
throw new ArgumentException("UnexpectedNullValue"); | |
builder.Append(EscapeUriDataStringRfc3986(pair.Key)); | |
builder.Append('='); | |
builder.Append(EscapeUriDataStringRfc3986(pair.Value)); | |
builder.Append('&'); | |
} | |
builder.Length--; | |
return builder.ToString(); | |
} | |
public static string EscapeUriDataStringRfc3986(string value) { | |
if (value == null) throw new ArgumentNullException("value"); | |
StringBuilder builder = new StringBuilder(Uri.EscapeDataString(value)); | |
for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++) { | |
builder.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0])); | |
} | |
return builder.ToString(); | |
} | |
public static void AddItemIfNotEmpty(this IDictionary<string, string> dictionary, string key, string value) { | |
if (key == null) { | |
throw new ArgumentNullException("key"); | |
} | |
if (!string.IsNullOrEmpty(value)) { | |
dictionary[key] = value; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment