Google integation in windows phone 8.1[RT] application - c#

I am working with windows phone 8.1 application and I want to login with Google Plus , for that I have create Client id and Client secret from Google
string uri = string.Format("{0}?response_type=code&client_id={1}&redirect_uri={2}&scope={3}&approval_prompt=force",
authEndpoint,
clientId,
"urn:ietf:wg:oauth:2.0:oob",
scope);
webBrowser.Navigate(new Uri(uri, UriKind.Absolute));
and I Got string something like 4/BGIl1Na3TQJlAD8SQ7blvHyONJ_Jyav8COHa7tIrAdo
I want User Email and Name from account for signup or login
Please help me for that.
Thank you

Implement the interafce IWebAuthenticationContinuable to your class and then under ContinueWebAuthentication() Method use this code :
var authData = GetGoogleSuccessCode(args.WebAuthenticationResult.ResponseData);
var userData = await GetTokenAndUserInfo(authData);
private string GetGoogleSuccessCode(string data)
{
if (string.IsNullOrEmpty(data)) return null;
var parts = data.Split('&')[0].Split('=');
for (int i = 0; i < parts.Length; ++i)
{
if (parts[i] == "Success code")
{
return parts[i + 1];
}
}
return null;
}
public async Task<string> GetTokenAndUserInfo(string code)
{
var client = new HttpClient();
var auth = await client.PostAsync("https://accounts.google.com/o/oauth2/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("client_id",Constants.GoogleAppId),
new KeyValuePair<string, string>("client_secret",Constants.GoogleAppSecret),
new KeyValuePair<string, string>("grant_type","authorization_code"),
new KeyValuePair<string, string>("redirect_uri","urn:ietf:wg:oauth:2.0:oob"),
}));
var data = await auth.Content.ReadAsStringAsync();
var j = JToken.Parse(data);
var token = j.SelectToken("access_token");
var searchUrl = "https://www.googleapis.com/oauth2/v2/userinfo";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token.ToString());
HttpResponseMessage res = await client.GetAsync(searchUrl);
string content = await res.Content.ReadAsStringAsync();
return content;
}
And add following code in App.xaml.cs file:
public static ContinuationManager ContinuationManager { get; private set; }
public App()
{
ContinuationManager = new ContinuationManager();
}
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
#if WINDOWS_PHONE_APP
ContinuationManager.MarkAsStale();
#endif
// TODO: Save application state and stop any background activity
deferral.Complete();
}
protected override void OnActivated(IActivatedEventArgs args)
{
#if WINDOWS_PHONE_APP
if (args.Kind == ActivationKind.WebAuthenticationBrokerContinuation)
{
var continuationEventArgs = args as IContinuationActivatedEventArgs;
if (continuationEventArgs != null)
{
ContinuationManager.Continue(continuationEventArgs);
ContinuationManager.MarkAsStale();
}
}
#endif
}
Don't forget to include Continuation Manager class file in your project.
You will get the user info.

I'm not an expert.
It looks like you need to request the email scope:
https://developers.google.com/+/web/api/rest/oauth#login-scopes
as well as (probably) the profile scope (same page).
If this isn't helpful, please edit your question and show more of your code (obscuring your secret API key, etc.).

I have also searched for sign in using facebook and google in WIN RT Apps and finally found solution from this link :
Web authentication broker sample
Maybe it will help you also.

Related

C# Response = "WaitingForActivation"

I have an asp.net website which sends a tweet on a button click event.
I am using the TwitterApi for this and have an authenticated developer account.
This function was working from September 2018 until last month, but all of a sudden it won't send the tweets on request.
The response I get now is - "Id = 1, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}""
After searching around, this doesn't seem like a twitter error, but an async error of some kind. I have made some minor alterations to my website in this time, but I cant see anything I have changed that would cause this issue.
The code is below.
Can any one see why this error would occur?
protected void Publish_Click(object sender, EventArgs e)
{
DataAccess.Publish();
SendEmails();
SendTweet();
Response.Redirect("OtherPage.aspx");
}
public static void SendTweet()
{
string text = DataAccess.GetText();
var twitter = new TwitterApi();
var response = twitter.Tweet(text);
}
public TwitterApi()
{
this.consumerKey = "XXX";
this.consumerKeySecret = "XXX";
this.accessToken = "XXX";
this.accessTokenSecret = "XXX";
sigHasher = new HMACSHA1(new ASCIIEncoding().GetBytes(string.Format("{0}&{1}", consumerKeySecret, accessTokenSecret)));
}
public Task<string> Tweet(string text)
{
var data = new Dictionary<string, string> {
{ "status", text },
{ "trim_user", "1" }
};
return SendRequest("statuses/update.json", data);
}
Task<string> SendRequest(string url, Dictionary<string, string> data)
{
var fullUrl = TwitterApiBaseUrl + url;
// Timestamps are in seconds since 1/1/1970.
var timestamp = (int)((DateTime.UtcNow - epochUtc).TotalSeconds);
// Add all the OAuth headers we'll need to use when constructing the hash.
data.Add("oauth_consumer_key", consumerKey);
data.Add("oauth_signature_method", "HMAC-SHA1");
data.Add("oauth_timestamp", timestamp.ToString());
data.Add("oauth_nonce", "a"); // Required, but Twitter doesn't appear to use it, so "a" will do.
data.Add("oauth_token", accessToken);
data.Add("oauth_version", "1.0");
// Generate the OAuth signature and add it to our payload.
data.Add("oauth_signature", GenerateSignature(fullUrl, data));
// Build the OAuth HTTP Header from the data.
string oAuthHeader = GenerateOAuthHeader(data);
// Build the form data (exclude OAuth stuff that's already in the header).
var formData = new FormUrlEncodedContent(data.Where(kvp => !kvp.Key.StartsWith("oauth_")));
return SendRequest(fullUrl, oAuthHeader, formData);
}
async Task<string> SendRequest(string fullUrl, string oAuthHeader, FormUrlEncodedContent formData)
{
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Add("Authorization", oAuthHeader);
var httpResp = await http.PostAsync(fullUrl, formData);
var respBody = httpResp.ToString();
return respBody;
}
}

Download a file through http basic authentication with Xamarin Android

I am accessing to an Enterprise Intranet using a WebView, in a Xamarin Android app. I can see and navigate correctly through the intranet but I am not able to download the files available there. This is my code :
private void MWebview_Download(object sender, DownloadEventArgs e)
{
var url = e.Url;
// var s = url.Replace(" ", "%20");
DownloadManager.Request request = new DownloadManager.Request(Android.Net.Uri.Parse(url));
string credentials = "cristina.casas:Tst.30"; //just for try
// pasar las credenciales a base64
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(credentials);
var encodedCredentials = System.Convert.ToBase64String(plainTextBytes);
request.AddRequestHeader("Authorization", "Basic " + encodedCredentials);
request.SetTitle("descarga.pdf");
request.SetNotificationVisibility(DownloadVisibility.VisibleNotifyCompleted);
request.AllowScanningByMediaScanner();
request.SetMimeType("application/pdf");
request.SetDestinationInExternalPublicDir(Android.OS.Environment.DirectoryDownloads, "descarga.pdf");
DownloadManager dm = (DownloadManager)Application.Context.GetSystemService(Context.DownloadService);
dm.Enqueue(request);
Toast.MakeText(Application.Context, "Downloading File", ToastLength.Long).Show();//To notify the Client that the file is being downloaded
}
It doesn't work. I get the error "download failed". I am stucked at this point for days...
Your code looks correct. Try the following as this works as a basic authentication test using HttpWatch's website. If it works for you, substitute your intranet's uri, user and password.
DownloadCompleteReceiver receiver;
var user = "httpwatch";
var password = new Random().Next(int.MinValue, int.MaxValue).ToString();
var uriString = "https://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.05205263447822417";
using (var uri = Android.Net.Uri.Parse(uriString))
using (var request = new DownloadManager.Request(uri))
{
var basicAuthentication = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{password}"));
request.AddRequestHeader("Authorization", $"Basic {basicAuthentication}");
request.SetNotificationVisibility(DownloadVisibility.VisibleNotifyCompleted);
request.SetDestinationInExternalPublicDir(Android.OS.Environment.DirectoryDownloads, "someImage.gif");
using (var downloadManager = (DownloadManager)GetSystemService(DownloadService))
{
var id = downloadManager.Enqueue(request);
receiver = new DownloadCompleteReceiver(id, (sender, e) =>
{
Toast.MakeText(Application.Context, $"Download Complete {id}", ToastLength.Long).Show();
if (sender is DownloadCompleteReceiver rec)
{
UnregisterReceiver(rec);
rec.Dispose();
}
});
RegisterReceiver(receiver, new IntentFilter(DownloadManager.ActionDownloadComplete));
Toast.MakeText(Application.Context, $"Downloading File: {id}", ToastLength.Short).Show();
}
}
The DownloadCompleteReceiver implementation is:
public class DownloadCompleteReceiver : BroadcastReceiver
{
long id;
EventHandler handler;
public DownloadCompleteReceiver(long id, EventHandler handler)
{
this.id = id;
this.handler = handler;
}
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == DownloadManager.ActionDownloadComplete &&
id == intent.GetLongExtra(DownloadManager.ExtraDownloadId, 0))
{
handler.Invoke(this, EventArgs.Empty);
}
}
}

Remembering log in credentials/permissions UWP/C# (Microsoft Cloud API)

I'm creating an app that access the Microsoft Cloud API to get health data. It uses OAuth to log in when you hit the Sign In Button
private void signinButton_Click(object sender, RoutedEventArgs e)
{
UriBuilder uri = new UriBuilder("https://login.live.com/oauth20_authorize.srf");
var query = new StringBuilder();
query.AppendFormat("redirect_uri={0}", Uri.EscapeDataString(RedirectUri));
query.AppendFormat("&client_id={0}", Uri.EscapeDataString(ClientId));
query.AppendFormat("&scope={0}", Uri.EscapeDataString(Scopes));
query.Append("&response_type=code");
uri.Query = query.ToString();
this.webView.Visibility = Visibility.Visible;
this.webView.Navigate(uri.Uri);
}
This brings up a webView with the page to log in using Microsoft credentials. Once completed, it leads to this:
private async void WebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
//
// When the web view navigates to our redirect URI, extract the authorization code from
// the URI and use it to fetch our access token. If no authorization code is present,
// we're completing a sign-out flow.
//
if (args.Uri.LocalPath.StartsWith("/oauth20_desktop.srf", StringComparison.OrdinalIgnoreCase))
{
WwwFormUrlDecoder decoder = new WwwFormUrlDecoder(args.Uri.Query);
var code = decoder.FirstOrDefault((entry) => entry.Name.Equals("code", StringComparison.OrdinalIgnoreCase));
var error = decoder.FirstOrDefault((entry) => entry.Name.Equals("error", StringComparison.OrdinalIgnoreCase));
var errorDesc = decoder.FirstOrDefault((entry) => entry.Name.Equals("error_description", StringComparison.OrdinalIgnoreCase));
// Check the code to see if this is sign-in or sign-out
if (code != null)
{
// Hide the browser again, no matter what happened...
sender.Visibility = Visibility.Collapsed;
if (error != null)
{
this.responseText.Text = string.Format("{0}\r\n{1}", error.Value, errorDesc.Value);
return;
}
var tokenError = await this.GetToken(code.Value, false);
if (string.IsNullOrEmpty(tokenError))
{
this.responseText.Text = "Successful sign-in!";
this.signoutButton.IsEnabled = true;
this.signinButton.IsEnabled = false;
this.getProfileButton.IsEnabled = true;
this.getDevicesButton.IsEnabled = true;
this.getActivitiesButton.IsEnabled = true;
this.getDailySummaryButton.IsEnabled = true;
this.getHourlySummaryButton.IsEnabled = true;
}
else
{
this.responseText.Text = tokenError;
}
}
else
{
this.responseText.Text = "Successful sign-out!";
this.signoutButton.IsEnabled = false;
this.signinButton.IsEnabled = true;
this.getProfileButton.IsEnabled = false;
this.getDevicesButton.IsEnabled = false;
this.getActivitiesButton.IsEnabled = false;
this.getDailySummaryButton.IsEnabled = true;
this.getHourlySummaryButton.IsEnabled = false;
}
}
}
private async Task<string> GetToken(string code, bool isRefresh)
{
UriBuilder uri = new UriBuilder("https://login.live.com/oauth20_token.srf");
var query = new StringBuilder();
query.AppendFormat("redirect_uri={0}", Uri.EscapeDataString(RedirectUri));
query.AppendFormat("&client_id={0}", Uri.EscapeDataString(ClientId));
query.AppendFormat("&client_secret={0}", Uri.EscapeDataString(ClientSecret));
if (isRefresh)
{
query.AppendFormat("&refresh_token={0}", Uri.EscapeDataString(code));
query.Append("&grant_type=refresh_token");
}
else
{
query.AppendFormat("&code={0}", Uri.EscapeDataString(code));
query.Append("&grant_type=authorization_code");
}
uri.Query = query.ToString();
var request = WebRequest.Create(uri.Uri);
try
{
using (var response = await request.GetResponseAsync())
{
using (var stream = response.GetResponseStream())
{
using (var streamReader = new StreamReader(stream))
{
var responseString = streamReader.ReadToEnd();
var jsonResponse = JObject.Parse(responseString);
this.creds.AccessToken = (string)jsonResponse["access_token"];
this.creds.ExpiresIn = (long)jsonResponse["expires_in"];
this.creds.RefreshToken = (string)jsonResponse["refresh_token"];
string error = (string)jsonResponse["error"];
return error;
}
}
}
}
catch (Exception ex)
{
return ex.Message;
}
}
I don't want users to have to accept the permissions every time the app is launched. Is there a way to save credentials locally so that it automatically authenticates on launch? Thanks!
You can use
Windows.Storage.ApplicationData.Current.LocalSettings
This process good described by this answer Best Way to keep Settings for a WinRT App?
The code in link identity to UWP
Store the needed oauth parts in the credential locker API. Never store these kind of information in the normal settings API.
On start read the oauth information and use the refreshtoken to get a new access token.
More Information here.
https://msdn.microsoft.com/en-us/library/windows/apps/mt270189.aspx

How to make an "apprequest" with c# Facebook SDK?

I would like to make an apprequest from my application using the c# facebook sdk.
After some investigation I found some examples that are using the app access token which has the following format : access_token = YOUR_APP_ID|YOU_APP_SECRET
Now I have tried the following using the appAccessToken:
string appAccessToken = String.Format("{0}|{1}",Constants.FacebookAppId,Constants.FacebookAppSecret);
FacebookClient fb = new FacebookClient(appAccessToken);
fb.PostCompleted += (o, args) =>
{
if (args.Error != null)
{
Dispatcher.BeginInvoke(() => MessageBox.Show(args.Error.Message));
return;
}
};
dynamic parameters = new ExpandoObject();
parameters.message = "Test: Action is required";
parameters.data = "Custom Data Here";
fb.PostTaskAsync(String.Format("{0}/apprequests", Constants.FacebookAppId), parameters);
But it doesn't work... Is it possible to make an apprequest using the c# Facebook skd?
I hope anybody can help me.
Have a nice day!
With best regards, Matthias
To get access token of App.
Just use this link and you will get it
https://developers.facebook.com/tools/access_token/
Please check this out : http://facebooksdk.net/docs/phone/tutorial.
To get user access token
Add this to App.xaml.cs
internal static string AccessToken = String.Empty;
internal static string FacebookId = String.Empty;
public static bool IsAuthenticated = false;
public static FacebookSessionClient FacebookSessionClient = new FacebookSessionClient(Constants.FacebookAppId);
Create a method to get Access token
private async Task Authenticate()
{
try
{
_session = await App.FacebookSessionClient.LoginAsync("user_about_me,read_stream");
App.AccessToken = _session.AccessToken;
App.FacebookId = _session.FacebookId;
}
catch (InvalidOperationException e)
{
var messageBox = new OneButtonCustomMessageBox
{
TbMessageTitle = { Text = "Facebook Login Error" },
TbMessageContent = {Text = e.Message}
};
messageBox.Show();
}
}
After you have Access Token you will use a method like this to call GraphAPI from FB to get user information
private async void LoadUserInfo()
{
var fb = new FacebookClient(App.AccessToken);
fb.GetCompleted += (o, e) =>
{
if (e.Error != null)
{
Dispatcher.BeginInvoke(() => MessageBox.Show(e.Error.Message));
return;
}
var result = (IDictionary<string, object>)e.GetResultData();
Dispatcher.BeginInvoke(async () =>
{
var profilePictureUrl = string.Format("https://graph.facebook.com/{0}/picture?type={1}&access_token={2}", App.FacebookId, "normal", App.AccessToken);
this.ImgAvatar.Source = new BitmapImage(new Uri(profilePictureUrl));
this.TxtName.Text = String.Format("{0}", (string)result["name"]);
});
};
await fb.GetTaskAsync("me");
}

Load text from web during xml parsing in Windows 8 Async

I have a unique issue, I want to get the name of an application from it's AppID while I convert an XML file into objects. This is the code I'm using at present:
if (xdoc.Element("Application") != null)
{
var data = from query in xdoc.Descendants("AppID")
select new APP
{
AppID = query.Value,
AppName = GetName(query.Value).ToString(),
};
itemGridView.DataContext = data;
}
This is the code I'm using to convert the GUID into an app name using Microsoft's Store API. I can confirm that it does return the app name. I'm just unsure how I can get this to display.
private async Task<string> GetName(string guid)
{
try
{
string link = "https://services.apps.microsoft.com/browse/6.2.9200-1/615/en-NZ_en-NZ/c/NZ/cp/10005001/Apps/{0}";
string url = string.Format(link, guid);
var httpClient = new HttpClient();
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
var response = await httpClient.SendAsync(httpRequestMessage);
var xmlString = await response.Content.ReadAsStringAsync();
XmlDocument NameXML = new XmlDocument();
NameXML = await XmlDocument.LoadFromUriAsync(new Uri(url));
string sAppName = NameXML.GetElementsByTagName("T")[0].ChildNodes[0].NodeValue.ToString();
return sAppName;
}
catch(Exception)
{
return guid;
}
}
I think my problem is with the async / await tasks. I've just been exposed to it now... how would I load up the App Name alongside the AppID when I parse the xml file?
The output that's being displayed when I run the app is "System.Threading.Tasks.Task[System.String]" (The objects load and the links and everything works fine, its just that the above is displayed instead of the app name).
I've been debugging using breakpoints, it appears that the GetName method only seems to be triggered later on, I'm not sure however.
Try to change this line :
AppName = GetName(query.Value).ToString(),
To this :
AppName = await GetName(query.Value),
GetName will return Task<string> instead of string when not awaited. And the method where above code resides required to be async because of using await inside that method :
private async void SomeMethod()
{
....
if (xdoc.Element("Application") != null)
{
var data = from query in xdoc.Descendants("AppID")
select new APP
{
AppID = query.Value,
AppName = await GetName(query.Value),
};
itemGridView.DataContext = data;
}
....
}
UPDATE :
As you already noticed, LINQ has very limited support for async/await currently. So to workaround this limitation, we can use normal for loop to avoid calling async function inside LINQ :
private async void SomeMethod()
{
....
if (xdoc.Element("Application") != null)
{
var query = from query in xdoc.Descendants("AppID")
select query.Value;
var data = new List<App>();
foreach (var q in query)
{
data.Add(new App{ AppId = q, AppName = await GetName(q) });
}
itemGridView.DataContext = data;
}
....
}

Categories

Resources