我正在使用Azure移动服务来授权用户,现在我正尝试从提供商处获取其他用户信息。除了Twitter之外,我还为所有人工作。要对所有其他人进行身份验证,我正在使用类似的内容:
var identities = await user.GetIdentitiesAsync();
var result = new JObject();
var fb = identities.OfType<FacebookCredentials>().FirstOrDefault();
if (fb != null)
{
var accessToken = fb.AccessToken;
result.Add("facebook", await GetProviderInfo("https://graph.facebook.com/me?access_token=" + accessToken));
}
我可以做这样的事情:
var tw = identities.OfType<TwitterCredentials>().FirstOrDefault();
if (tw != null)
{
var accessToken = tw.AccessToken;
var accessTokenSecret = tw.AccessTokenSecret;
result.Add("twitter", await
GetProviderInfo("https://api.twitter.com/1.1/account/verify_credentials.json?token=" + accessToken + "&token_secret=" + accessTokenSecret + "&consumer_key=***************" + "&consumer_secret=******************************"));
}
还是我必须做一些完全不同的事情?
Woops,刚刚在这里找到了类似的问题:Twitter single url request
答案 0 :(得分:1)
是的,这是可能的,但它比其他提供商的工作更多。
这是你的api控制器的代码(可能需要一些重构)
[HttpPost]
[Route("current/identity")]
public async Task<HttpResponseMessage> GetIdentityInfo()
{
var currentUser = User as ServiceUser;
if (currentUser != null)
{
var identities = await currentUser.GetIdentitiesAsync();
var googleCredentials = identities.OfType<GoogleCredentials>().FirstOrDefault();
if (googleCredentials != null)
{
var infos = await GetGoolgeDetails(googleCredentials);
return Request.CreateResponse(HttpStatusCode.OK, infos);
}
var facebookCredentials = identities.OfType<FacebookCredentials>().FirstOrDefault();
if (facebookCredentials!= null)
{
var infos = await GetFacebookDetails(facebookCredentials);
return Request.CreateResponse(HttpStatusCode.OK, infos);
}
var microsoftCredentials = identities.OfType<MicrosoftAccountCredentials>().FirstOrDefault();
if (microsoftCredentials != null)
{
var infos = await GetMicrosoftDetails(microsoftCredentials);
return Request.CreateResponse(HttpStatusCode.OK, infos);
}
var twitterCredentials = identities.OfType<TwitterCredentials>().FirstOrDefault();
if (twitterCredentials != null)
{
var infos = await GetTwitterDetails(currentUser, twitterCredentials);
return Request.CreateResponse(HttpStatusCode.OK, infos);
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
private async Task<JToken> GetTwitterDetails(ServiceUser currentUser, TwitterCredentials twitterCredentials)
{
var twitterId = currentUser.Id.Split(':').Last();
var accessToken = twitterCredentials.AccessToken;
string consumerKey = ConfigurationManager.AppSettings["MS_TwitterConsumerKey"];
string consumerSecret = ConfigurationManager.AppSettings["MS_TwitterConsumerSecret"];
// Add this setting manually on your Azure Mobile Services Management interface.
// You will find the secret on your twitter app configuration
string accessTokenSecret = ConfigurationManager.AppSettings["FG_TwitterAccessTokenSecret"];
var parameters = new Dictionary<string, string>();
parameters.Add("user_id", twitterId);
parameters.Add("oauth_token", accessToken);
parameters.Add("oauth_consumer_key", consumerKey);
OAuth1 oauth = new OAuth1();
string headerString = oauth.GetAuthorizationHeaderString(
"GET", "https://api.twitter.com/1.1/users/show.json",
parameters, consumerSecret, accessTokenSecret);
var infos = await GetProviderInfo("https://api.twitter.com/1.1/users/show.json?user_id=" + twitterId, headerString);
return infos;
}
private async Task<JToken> GetMicrosoftDetails(MicrosoftAccountCredentials microsoftCredentials)
{
var accessToken = microsoftCredentials.AccessToken;
var infos = await GetProviderInfo("https://apis.live.net/v5.0/me/?method=GET&access_token=" + accessToken);
return infos;
}
private async Task<JToken> GetFacebookDetails(FacebookCredentials facebookCredentials)
{
var accessToken = facebookCredentials.AccessToken;
var infos = await GetProviderInfo("https://graph.facebook.com/me?access_token=" + accessToken);
return infos;
}
private async Task<JToken> GetGoolgeDetails(GoogleCredentials googleCredentials)
{
var accessToken = googleCredentials.AccessToken;
var infos = await GetProviderInfo("https://www.googleapis.com/oauth2/v3/userinfo?access_token=" + accessToken);
return infos;
}
private async Task<JToken> GetProviderInfo(string url, string oauth1HeaderString = null)
{
using (var client = new HttpClient())
{
if (oauth1HeaderString != null)
{
client.DefaultRequestHeaders.Authorization = System.Net.Http.Headers.AuthenticationHeaderValue.Parse(oauth1HeaderString);
}
var resp = await client.GetAsync(url).ConfigureAwait(false);
resp.EnsureSuccessStatusCode();
string rawInfo = await resp.Content.ReadAsStringAsync().ConfigureAwait(false);
return JToken.Parse(rawInfo);
}
}
然后,您需要此类来构建有效的OAuth 1.0身份验证标头:
(几乎所有以下代码都来自LinqToTwitter,https://linqtotwitter.codeplex.com)
public class OAuth1
{
const string OAUTH_VERSION = "1.0";
const string SIGNATURE_METHOD = "HMAC-SHA1";
const long UNIX_EPOC_TICKS = 621355968000000000L;
public string GetAuthorizationHeaderString(string method, string url, IDictionary<string, string> parameters, string consumerSecret, string accessTokenSecret)
{
string encodedAndSortedString = BuildEncodedSortedString(parameters);
string signatureBaseString = BuildSignatureBaseString(method, url, encodedAndSortedString);
string signingKey = BuildSigningKey(consumerSecret, accessTokenSecret);
string signature = CalculateSignature(signingKey, signatureBaseString);
string authorizationHeader = BuildAuthorizationHeaderString(encodedAndSortedString, signature);
return authorizationHeader;
}
internal void AddMissingOAuthParameters(IDictionary<string, string> parameters)
{
if (!parameters.ContainsKey("oauth_timestamp"))
parameters.Add("oauth_timestamp", GetTimestamp());
if (!parameters.ContainsKey("oauth_nonce"))
parameters.Add("oauth_nonce", GenerateNonce());
if (!parameters.ContainsKey("oauth_version"))
parameters.Add("oauth_version", OAUTH_VERSION);
if (!parameters.ContainsKey("oauth_signature_method"))
parameters.Add("oauth_signature_method", SIGNATURE_METHOD);
}
internal string BuildEncodedSortedString(IDictionary<string, string> parameters)
{
AddMissingOAuthParameters(parameters);
return
string.Join("&",
(from parm in parameters
orderby parm.Key
select parm.Key + "=" + PercentEncode(parameters[parm.Key]))
.ToArray());
}
internal virtual string BuildSignatureBaseString(string method, string url, string encodedStringParameters)
{
int paramsIndex = url.IndexOf('?');
string urlWithoutParams = paramsIndex >= 0 ? url.Substring(0, paramsIndex) : url;
return string.Join("&", new string[]
{
method.ToUpper(),
PercentEncode(urlWithoutParams),
PercentEncode(encodedStringParameters)
});
}
internal virtual string BuildSigningKey(string consumerSecret, string accessTokenSecret)
{
return string.Format(
CultureInfo.InvariantCulture, "{0}&{1}",
PercentEncode(consumerSecret),
PercentEncode(accessTokenSecret));
}
internal virtual string CalculateSignature(string signingKey, string signatureBaseString)
{
byte[] key = Encoding.UTF8.GetBytes(signingKey);
byte[] msg = Encoding.UTF8.GetBytes(signatureBaseString);
KeyedHashAlgorithm hasher = new HMACSHA1();
hasher.Key = key;
byte[] hash = hasher.ComputeHash(msg);
return Convert.ToBase64String(hash);
}
internal virtual string BuildAuthorizationHeaderString(string encodedAndSortedString, string signature)
{
string[] allParms = (encodedAndSortedString + "&oauth_signature=" + PercentEncode(signature)).Split('&');
string allParmsString =
string.Join(", ",
(from parm in allParms
let keyVal = parm.Split('=')
where parm.StartsWith("oauth") || parm.StartsWith("x_auth")
orderby keyVal[0]
select keyVal[0] + "=\"" + keyVal[1] + "\"")
.ToList());
return "OAuth " + allParmsString;
}
internal virtual string GetTimestamp()
{
long ticksSinceUnixEpoc = DateTime.UtcNow.Ticks - UNIX_EPOC_TICKS;
double secondsSinceUnixEpoc = new TimeSpan(ticksSinceUnixEpoc).TotalSeconds;
return Math.Floor(secondsSinceUnixEpoc).ToString(CultureInfo.InvariantCulture);
}
internal virtual string GenerateNonce()
{
return new Random().Next(111111, 9999999).ToString(CultureInfo.InvariantCulture);
}
internal virtual string PercentEncode(string value)
{
const string ReservedChars = @"`!@#$^&*()+=,:;'?/|\[] ";
var result = new StringBuilder();
if (string.IsNullOrWhiteSpace(value))
return string.Empty;
var escapedValue = Uri.EscapeDataString(value);
// Windows Phone doesn't escape all the ReservedChars properly, so we have to do it manually.
foreach (char symbol in escapedValue)
{
if (ReservedChars.IndexOf(symbol) != -1)
{
result.Append('%' + String.Format("{0:X2}", (int)symbol).ToUpper());
}
else
{
result.Append(symbol);
}
}
return result.ToString();
}
}