Facebook authentication shows deprecated method error - windows-phone-7

I'm using the Facebook C# SDK and trying to authenticate my user. The first part sort of worked, my app showed me the facebook login page inside a browser control.
This is the code I have, I was following this example.
private readonly FacebookClient _fb = new FacebookClient();
private void Browser_Loaded(object sender, RoutedEventArgs e)
{
var loginUrl = GetFacebookLoginUrl();
BrowserControl.Navigate(loginUrl);
}
private Uri GetFacebookLoginUrl()
{
var parameters = new Dictionary<string, object>();
parameters["client_id"] = FacebookSettings.AppID;
parameters["redirect_uri"] = "https://www.facebook.com/connect/login_success.html";
parameters["response_type"] = "token";
parameters["display"] = "page";
if (!string.IsNullOrEmpty(FacebookSettings.ExtendedPermissions))
parameters["scope"] = FacebookSettings.ExtendedPermissions;
return _fb.GetLoginUrl(parameters);
}
After I filled in my details to log into facebook, I got this error:
Any idea's which method is deprecated and how I can fix this?

I used the same code and it's working. And such an error is occuring because of a bug in the facebook API, when display parameter is set to "touch" or "wap". That shouldn't occur when using "page". Try using "popup" as the display.
Try changing the july 2012 Breaking Changes in the app's advanced settings tab(in developer.facebook.com). Refer to this link for information on this issue. And similar issue in facebook developer site.

Related

Using libVLCsharp to stream pw protected IP Camera Video but video not playing

I am trying to construct a UI for Onvif complaint devices. I've been beating my head against the wall for sometime now. I believe I have the custom URI correctly constructed. According to the ONVIF Programmers Guide we need to Get Profiles, GetStreamURI, Request Streaming. http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf
Using Wireshark I believe I see HTTP packets being sent (showing the appropriate requests), and what I believe are appropriate responses. The final GetStreamURI gets a successful response from the camera. Then when I try to call _mp.Play I see a few packets over HTTP and a few TCP packets back back from the camera. After this communication stops.
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LibVLCSharp.Shared;
using LibVLCSharp;
using System.ServiceModel.Channels;
using Lib_vlc_CSharp_Onvif.OnvifDevice;
using System.ServiceModel;
using Lib_vlc_CSharp_Onvif.OnvifMedia;
namespace Lib_vlc_CSharp_Onvif
{
public partial class Form1 : Form
{
public LibVLC _libVLC;
public LibVLCSharp.Shared.MediaPlayer _mp;
public LibVLCSharp.Shared.Media media;
//ToDO... make screen size adjustable
public System.Drawing.Size VidSize;
public System.Drawing.Size FormSize;
public System.Drawing.Point OldVidLoc;
//Create Onvif Media Profiles through service references
OnvifMedia.Media2Client Onvif_media;
OnvifMedia.MediaProfile[] profiles;
//Custom URI variable
UriBuilder deviceUri;
public Form1()
{
InitializeComponent();
//LibVLCSharp Specific
Core.Initialize();
this.KeyPreview = true;
//Just controlling the size. TODO: Imp controls
VidSize = videoView.Size;
FormSize = this.Size;
OldVidLoc = videoView.Location;
//Vlc Specific
//Set up the Vlc Lib and then connect the Form1 media window player to the media player of the library.
//videoVew is vlcsharp item in Form1.
_libVLC = new LibVLC();
_mp = new MediaPlayer(_libVLC);
videoView.MediaPlayer = _mp;
}
private void button1_Click(object sender, EventArgs e)
{
//Set up device to get profiles (Onvif Specific)
//Required a custom URI and binding.
deviceUri = new UriBuilder("Http:/onvif/device_service");
System.ServiceModel.Channels.Binding binding;
HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
httpTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Digest;
binding = new CustomBinding(new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), httpTransport);
//Assign IP Address to device URI. TODO: This eventually will be pulled from user entered value in an text box.
deviceUri.Host = "xxx.xxx.x.x";
DeviceClient Onvif_Device = new DeviceClient(binding, new EndpointAddress(deviceUri.ToString()));
OnvifDevice.Service[] service = Onvif_Device.GetServices(false);
//Check if they contain media and that we have made contact TODO wrap in a try catch block
OnvifDevice.Service xmedia = service.FirstOrDefault(s => s.Namespace == "http://www.onvif.org/ver20/media/wsdl");
if (xmedia != null)
{
Onvif_media = new Media2Client(binding, new EndpointAddress(deviceUri.ToString()));
Onvif_media.ClientCredentials.HttpDigest.ClientCredential.UserName = "admin";
Onvif_media.ClientCredentials.HttpDigest.ClientCredential.Password = "admin";
Onvif_media.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//Get camera Profiles.
profiles = Onvif_media.GetProfiles(null, null);
if (profiles != null)
{
foreach (var p in profiles)
{
listBox.Items.Add(p.Name);
//Profiles listed in box match profiles setup on camera.
}
}
}
//Eventually add a selection option on the list box.
//listBox.SelectedINdexChanged += OnSelectionChanged
//If we have profiles build a custom URI to past to the vlc boject
if (profiles != null)
{
//Building URI to pass to VLCSharp VideoView Item.
//https://www.onvif.org/ver20/media/wsdl/media.wsdl
//GetSreamUri and define RtspUnicast.
//http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf on page 57&58
UriBuilder local_uri = new UriBuilder(Onvif_media.GetStreamUri("RtspUnicast", profiles[0].token));
//ToDO: Build list box to allow user to switch between profiles. Just past main profile for now.
local_uri.Host = deviceUri.Host;
local_uri.Port = deviceUri.Port;
local_uri.Scheme = "rtsp";
//List full URI info.
infoBox.Text = local_uri.Host + local_uri.Port + local_uri.Path;
//Past it to VideoView and start playing video.
_mp.Play(new Media(_libVLC, local_uri.Uri));
}
}
}
}
Update: I believe my issue is the URI I have built requires validation. When I take this URI and put it into a web browser I get a 401 Error. I'm not sure why I don't see this error on wire-shark. I assign the user name and password into URI object but when I check "IsWellFormedURIString" I get an "invalid Port Error."
Did you try --rtsp-user and --rtsp-pwd ? you could also set the RTSP password with the dialog API.
If that doesn't work, please share your full logs.
You should be able to copy/paste the URL from Onvif Device Manager right into VLC and see it play (provided that you entered the correct credentials). If it doesn't, that's already an issue on its own.
You can still assign the Password and Username password.
MyUri.UserName = MyName
MyUri.Password = password
You run into problems when your password has characters like "#"
While I haven't figured out a workaround on this, for the time being keeping the password simple like "MyPassword" instead of "MyPassword#1234" will allow you to use the URI with the name and password built into the string.

ADAL invalid redirect uri

Note: i'm using an experimental pre-release of microsoft's latest adal
I'm trying to get my identity providers to work on the mobile applications. So far I've been able to load my identity providers and managed to get the login page to show (except for facebook).
The problem is that whenever i actually try to login i'm getting some error in the form off "invalid redirect uri".
Google, for instance, will say: "The redirect URI in the request: https://login.microsoftonline.com/... did not match a registered redirect URI.
Facebook will show: "Given URL is not allowed by the application configuration: One or more of the given URLs is not allowed by the App's settings. It must match the website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains."
As far as I understand you don't actually need to register the mobile application anymore with the different identity providers because Azure sits in between you and them. Azure handles the connection, gets your token and uses it to identify you. It should then return a set of "azure tokens" to you.
To my knowledge the used redirect URI is registered on the portal since I'm able to load the identity providers in the first place?
Not to mention it seems to be a default URL that's used by many applications: urn:ietf:wg:oauth:2.0:oob which simply tells it to return it to some none-browser based application?
This is the code i'm using to actually do the login/signup:
private static String AUTHORITY_URL = "https://login.microsoftonline.com/<directory>/oauth2/authorize/";
private static String CLIENT_ID = "my_client_id";
private static String[] SCOPES = { "my_client_id" };
private static String[] ADDITIONAL_SCOPES = { "" };
private static String REDIRECT_URL = "urn:ietf:wg:oauth:2.0:oob";
private static String CORRELATION_ID = "";
private static String USER_HINT = "";
private static String EXTRA_QP = "nux=1";
private static String FB_POLICY = "B2C_1_<your policy>";
private static String EMAIL_SIGNIN_POLICY = "B2C_1_SignIn";
private static String EMAIL_SIGNUP_POLICY = "B2C_1_SignUp";
public async Task<AuthenticationResult> Login(IPlatformParameters parameters, bool isSignIn)
{
var authContext = new AuthenticationContext(AUTHORITY_URL, new TokenCache());
if (CORRELATION_ID != null &&
CORRELATION_ID.Trim().Length != 0)
{
authContext.CorrelationId = Guid.Parse(CORRELATION_ID);
}
String policy = "";
if (isSignIn)
policy = EMAIL_SIGNIN_POLICY;
else
policy = EMAIL_SIGNUP_POLICY;
return await authContext.AcquireTokenAsync(SCOPES, ADDITIONAL_SCOPES, CLIENT_ID, new Uri(REDIRECT_URL), parameters, UserIdentifier.AnyUser, EXTRA_QP, policy);
}
microsoft's documentation isn't really helping because most are either empty (they're literally not yet typed out) or it's some help topic from over a year ago. This stuff is pretty new so documentation seems to be hard to come by.
So, dear people of stackoverflow, what am I missing? Why is it saying that the redirect urI is invalid when it's been registered on the azure web portal? And if the redirect URI is invalid why can I retrieve the identity providers in the first place?
why is it that i can't seem to find solutions after hours of searching, yet when i post a question here i somehow find the answer within minutes...
It was quite a stupid mistake at that, one of my collegues had sent me the wrong authority url.
The funny thing is that it was correct "enough" to load the identity providers we had installed on the portal but not correct enough to handle actually signing in or up.
I initially used:
https://login.microsoftonline.com/<tenant_id>/oauth2/authorize/
where it should have been:
https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize
You see that little "v2.0"? yeah that little bastard is what caused all the pain...

Google+ insert moment using google-api-dotnet-client

I am trying to write an activity in Google+ using the dotnet-client. The issue is that I can't seem to get the configuration of my client app correctly. According to the Google+ Sign-In configuration and this SO question we need to add the requestvisibleactions parameter. I did that but it did not work. I am using the scope https://www.googleapis.com/auth/plus.login and I even added the scope https://www.googleapis.com/auth/plus.moments.write but the insert still did not work.
This is what my request url looks like:
https://accounts.google.com/ServiceLogin?service=lso&passive=1209600&continue=https://accounts.google.com/o/oauth2/auth?scope%3Dhttps://www.googleapis.com/auth/plus.login%2Bhttps://www.googleapis.com/auth/plus.moments.write%26response_type%3Dcode%26redirect_uri%3Dhttp://localhost/%26state%3D%26requestvisibleactions%3Dhttp://schemas.google.com/AddActivity%26client_id%3D000.apps.googleusercontent.com%26request_visible_actions%3Dhttp://schemas.google.com/AddActivity%26hl%3Den%26from_login%3D1%26as%3D-1fbe06f1c6120f4d&ltmpl=popup&shdf=Cm4LEhF0aGlyZFBhcnR5TG9nb1VybBoADAsSFXRoaXJkUGFydHlEaXNwbGF5TmFtZRoHQ2hpa3V0bwwLEgZkb21haW4aB0NoaWt1dG8MCxIVdGhpcmRQYXJ0eURpc3BsYXlUeXBlGgdERUZBVUxUDBIDbHNvIhTeWybcoJ9pXSeN2t-k8A4SUbfhsygBMhQivAmfNSs_LkjXXZ7bPxilXgjMsQ&scc=1
As you can see from there that there is a request_visible_actions and I even added one that has no underscore in case I got the parameter wrong (requestvisibleactions).
Let me say that my app is being authenticated successfully by the API. I can get the user's profile after being authenticated and it is on the "insert moment" part that my app fails. My insert code:
var body = new Moment();
var target = new ItemScope();
target.Id = referenceId;
target.Image = image;
target.Type = "http://schemas.google.com/AddActivity";
target.Description = description;
target.Name = caption;
body.Target = target;
body.Type = "http://schemas.google.com/AddActivity";
var insert =
new MomentsResource.InsertRequest(
// this is a valid service instance as I am using this to query the user's profile
_plusService,
body,
id,
MomentsResource.Collection.Vault);
Moment result = null;
try
{
result = insert.Fetch();
}
catch (ThreadAbortException)
{
// User was not yet authenticated and is being forwarded to the authorization page.
throw;
}
catch (Google.GoogleApiRequestException requestEx)
{
// here I get a 401 Unauthorized error
}
catch (Exception ex)
{
} `
For the OAuth flow, there are two issues with your request:
request_visible_actions is what is passed to the OAuth v2 server (don't pass requestvisibleactions)
plus.moments.write is a deprecated scope, you only need to pass in plus.login
Make sure your project references the latest version of the Google+ .NET client library from here:
https://developers.google.com/resources/api-libraries/download/stable/plus/v1/csharp
I have created a project on GitHub showing a full server-side flow here:
https://github.com/gguuss/gplus_csharp_ssflow
As Brettj said, you should be using the Google+ Sign-in Button as demonstrated in the latest Google+ samples from here:
https://github.com/googleplus/gplus-quickstart-csharp
First, ensure you are requesting all of the activity types you're writing. You will know this is working because the authorization dialog will show "Make your app activity available via Google, visible to you and: [...]" below the text that starts with "This app would like to". I know you checked this but I'm 90% sure this is why you are getting the 401 error code. The following markup shows how to render the Google+ Sign-In button requesting access to Add activities.
<div id="gConnect">
<button class="g-signin"
data-scope="https://www.googleapis.com/auth/plus.login"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-clientId="YOUR_CLIENT_ID"
data-accesstype="offline"
data-callback="onSignInCallback"
data-theme="dark"
data-cookiepolicy="single_host_origin">
</button>
Assuming you have a PlusService object with the correct activity type set in data-requestvisibleactions, the following code, which you should be able to copy/paste to see it work, concisely demonstrates writing moments using the .NET client and has been tested to work:
Moment body = new Moment();
ItemScope target = new ItemScope();
target.Id = "replacewithuniqueforaddtarget";
target.Image = "http://www.google.com/s2/static/images/GoogleyEyes.png";
target.Type = "";
target.Description = "The description for the activity";
target.Name = "An example of add activity";
body.Target = target;
body.Type = "http://schemas.google.com/AddActivity";
MomentsResource.InsertRequest insert =
new MomentsResource.InsertRequest(
_plusService,
body,
"me",
MomentsResource.Collection.Vault);
Moment wrote = insert.Fetch();
Note, I'm including Google.Apis.Plus.v1.Data for convenience.
Ah it's that simple! Maybe not? I am answering my own question and consequently accept it as the answer (after a few days of course) so others having the same issue may be guided. But I will definitely up-vote Gus' answer for it led me to the fix for my code.
So according to #class answer written above and as explained on his blog the key to successfully creating a moment is adding the request_visible_actions parameter. I did that but my request still failed and it is because I was missing an important thing. You need to add one more parameter and that is the access_type and it should be set to offline. The OAuth request, at a minimum, should look like: https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/plus.login&response_type=code&redirect_uri=http://localhost/&request_visible_actions=http://schemas.google.com/AddActivity&access_type=offline.
For the complete and correct client code you can get Gus' example here or download the entire dotnet client library including the source and sample and add what I added below. The most important thing that you should remember is modifying your AuthorizationServerDescription for the Google API. Here's my version of the authenticator:
public static OAuth2Authenticator<WebServerClient> CreateAuthenticator(
string clientId, string clientSecret)
{
if (string.IsNullOrWhiteSpace(clientId))
throw new ArgumentException("clientId cannot be empty");
if (string.IsNullOrWhiteSpace(clientSecret))
throw new ArgumentException("clientSecret cannot be empty");
var description = GoogleAuthenticationServer.Description;
var uri = description.AuthorizationEndpoint.AbsoluteUri;
// This is the one that has been documented on Gus' blog site
// and over at Google's (https://developers.google.com/+/web/signin/)
// This is not in the dotnetclient sample by the way
// and you need to understand how OAuth and DNOA works.
// I had this already, see my original post,
// I thought it will make my day.
if (uri.IndexOf("request_visible_actions") < 1)
{
var param = (uri.IndexOf('?') > 0) ? "&" : "?";
description.AuthorizationEndpoint = new Uri(
uri + param +
"request_visible_actions=http://schemas.google.com/AddActivity");
}
// This is what I have been missing!
// They forgot to tell us about this or did I just miss this somewhere?
uri = description.AuthorizationEndpoint.AbsoluteUri;
if (uri.IndexOf("offline") < 1)
{
var param = (uri.IndexOf('?') > 0) ? "&" : "?";
description.AuthorizationEndpoint =
new Uri(uri + param + "access_type=offline");
}
// Register the authenticator.
var provider = new WebServerClient(description)
{
ClientIdentifier = clientId,
ClientSecret = clientSecret,
};
var authenticator =
new OAuth2Authenticator<WebServerClient>(provider, GetAuthorization)
{ NoCaching = true };
return authenticator;
}
Without the access_type=offline my code never worked and it will never work. Now I wonder why? It would be good to have some explanation.

HttpWebRequest and WebClient returning NotFound on Windows Phone 7 but not i normal console application

I'm trying to download a regular JSON string from this url https://valueboxtest.lb.dk/mobile/categories from a Windows Phone 7 Application.
I have tried to both use WebClient and HttpWebRequest. They both throw an exception
“The remote server returned an error: NotFound”
This is the code for using the WebClient
var webClient = new WebClient();
webClient.DownloadStringCompleted += (client_DownloadStringCompleted);
webClient.DownloadStringAsync(new Uri("https://valueboxtest.lb.dk/mobile/categories"));
The eventhandler then just show the content, but e.Result throws the above mentioned exception:
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null && !e.Cancelled) MessageBox.Show(e.Result);
}
For the HttpWebRequest my code looks as follows:
var httpReq = (HttpWebRequest)WebRequest.Create(new Uri("https://valueboxtest.lb.dk/mobile/categories"));
httpReq.BeginGetResponse(HTTPWebRequestCallBack, httpReq);
With the following callback:
private void HTTPWebRequestCallBack(IAsyncResult result)
{
var httpRequest = (HttpWebRequest)result.AsyncState;
var response = httpRequest.EndGetResponse(result);
var stream = response.GetResponseStream();
var reader = new StreamReader(stream);
this.Dispatcher.BeginInvoke(
new delegateUpdate(update),
new Object[] { reader.ReadToEnd() }
);
}
And with the delegate method
delegate void delegateUpdate(string content);
private void update(string content)
{
MessageBox.Show(content);
}
Running it in a console application
Everything works just fine and the JSON string is returned with no problems and I am able to print the result to the console.
Different URL does work on WP7
The weird thing is that the URL http://mobiforge.com/rssfeed actually works fine in both of the above mentioned scenarios.
This issue occurs both in the Emulator and on an actual device.
What could be wrong? Is the REST service returning the data in misbehaving way? I really hope you can help me!
Note: I'm not running Fiddler2 at the same time!
The reason is because that site does not have a valid certificate. Just try it on Mobile Internet Explorer and you'll get the prompt about an issue with the certificate.
How to ignore SSL certificates
Mobile devices are stricter when it comes to SSL certificates.
If you want to get this app into a production environment, you'll either need to write a wrapper for this server (if it's not your own), or get a valid certificate. In the short-term, for testing, you can add a certificate into your device.
Here's a tool which might help you install a certificate.

Using webclient with htmlAgilityPack on wp7 to get html generated from javascript

i want to get the time schedule on
http://www.21cineplex.com/playnow/sherlock-holmes-a-game-of-shadows,2709.htm
first,
i have tried using webclient with htmlAgilityPack and get to the table id = "table-theater" but appearently the html generated from java script so the table innetHTML is empty.
public void LoadMovieShowTime(string MovieLink)
{
WebClient MovieShowTimeclient = new WebClient();
MovieShowTimeclient.DownloadStringAsync(new Uri(MovieLink));
MovieShowTimeclient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(MovieShowTimeclient_DownloadStringCompleted);
}
void MovieShowTimeclient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(e.Result);
var node = doc.DocumentNode.Descendants("div").First()
.Elements("div").Skip(1).First()
.Elements("div").Skip(1).First()
.Element("div")
.Elements("table").FirstOrDefault(table => table.Attributes["class"].Value == "table-theater");
}
Is it possible to get the data using webclient on windows phone? or is there any pssible way to get it using another method?
second,
i have tried to get the time schedule from mobile site which is
http://m.21cineplex.com/gui.list_schedule?sid=&movie_id=11SHGO&find_by=1&order=1
but the return ask me to enable cookies. im new to this, i find that there is a way to extend webclien ability by overriding the webRequest cookies, but cant find any reference how to use it.
thanks, for any reply and help :)
Just because the table is generated in JavaScript does not mean the WebBrowser control will not render it. Ensure that IsScriptEnabled is set to true, this will ensure that the JavaScript that renders the table is executed. You can then 'scrape' the results.

Resources