Google authentication Xamarin invalid redirect uri - xamarin

I need to make authentication using Google for my app (Xamarin Android Native). I used this article. I passed step by step. Also I created client id in Google Developer Console. But I have an error. The package name is displayed on the screenshot. What can be wrong with this?
public const string RedirectUrl = "com.xplorpal.pal_:/oauth2redirect";
_auth = new OAuth2Authenticator(clientId, string.Empty, scope,
new Uri(AuthorizeUrl),
new Uri(redirectUrl),
new Uri(AccessTokenUrl),
null, IsUsingNativeUI);

I think the problem is the underscore in the redirect URL:
public const string RedirectUrl = "com.xplorpal.pal:/oauth2redirect";
_auth = new OAuth2Authenticator(clientId, string.Empty, scope,
new Uri(AuthorizeUrl),
new Uri(redirectUrl),
new Uri(AccessTokenUrl),
null, IsUsingNativeUI);
Here you can find more info about why the UriFormatException is thrown. https://msdn.microsoft.com/it-it/library/z6c2z492(v=vs.110).aspx

Related

AcquireTokenSilentAsync not working

I have the following setup:
var authContext = new AuthenticationContext("https://login.microsoftonline.com/common");
string redirectUri = Url.Action("Authorize", "Planner", null, Request.Url.Scheme);
Uri authUri = authContext.GetAuthorizationRequestURL("https://graph.microsoft.com/", SettingsHelper.ClientId,
new Uri(redirectUri), UserIdentifier.AnyUser, null);
// Redirect the browser to the Azure signin page
return Redirect(authUri.ToString());
This takes you to:
// Get the 'code' parameter from the Azure redirect
string authCode = Request.Params["code"];
// The same url we specified in the auth code request
string redirectUri = Url.Action("Authorize", "Planner", null, Request.Url.Scheme);
// Use client ID and secret to establish app identity
ClientCredential credential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.ClientSecret);
//FileTokenCache at specific location
TokenCache fileTokenCache = new FilesBasedAdalV3TokenCache("C:\\temp\\justin.bin");
AuthenticationContext authContext = new AuthenticationContext(SettingsHelper.AzureADAuthorityTenantID, fileTokenCache);
AuthenticationResult authResult = null;
try
{
// Get the token silently first
authResult = await authContext.AcquireTokenSilentAsync(SettingsHelper.O365UnifiedResource, credential, UserIdentifier.AnyUser);
}
catch (AdalException ex)
{
authContext = new AuthenticationContext(SettingsHelper.AzureADAuthority, fileTokenCache);
authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(authCode, new Uri(redirectUri), credential, SettingsHelper.O365UnifiedResource);
}
The token is successfully saved in the file and it seems that it is also being successfully retrieved. However the silent token acquisition still gives an exception to get token first using the non silent function. What am I missing please?
Note that O365UnifiedResource is set to https://graph.microsoft.com/
solved this by using
new UserIdentifier("<email address used to login microsoft apps>", UserIdentifierType.RequiredDisplayableId)
instead of
UserIdentifier.AnyUser
and fixed the client ID to be the APP ID as specified in the registration of the app

Parameters are empty when submitting request for adapter authentication on Android

I use adapter authentication in my Xamarin.Forms app with the IBM MFP SDK. The adapter requires a username and a password.
In my iOS app (with the exact same shared code) everything works as it should.
In my Android app the parameters are empty (found that out using Charles / Fiddler).
I debugged the process and my Identity variable with username and password is not null and correctly filled in.
public override AdapterAuthenticationInfo GetAdapterAuthenticationParameters()
{
var parameters = new string[] { Identity.Email, Identity.Password };
var invocationData = new WorklightProcedureInvocationData("AuthAdapter", "submitAuthentication", parameters);
var authInfo = new AdapterAuthenticationInfo();
authInfo.InvocationData = invocationData;
return authInfo;
}
Can you try running your app using object array instead of string array and see if that works?
var parameters = new object[] { Identity.Email, Identity.Password };

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.

Facebook authentication shows deprecated method error

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.

Create Event C# SDK Failes - Getting (OAuthException) (#324) Missing or invalid image file

I am trying to create an event using the C# SDK. I am using the code from the following blog:
http://facebooksdk.blogspot.co.uk/2011/05/facebook-create-event.html
And I am using an image that I copied from an existing event on Facebook.
I am getting however the following error:
(OAuthException) (#324) Missing or invalid image file
Does anyone have an idea how to make it work?
Many thanks!
The code is as follows:
public string CreateEvent()
{
var fb = new FacebookWebClient();
Dictionary<string, object> createEventParameters = new Dictionary<string, object>();
createEventParameters.Add("name", "My birthday party )");
createEventParameters.Add("start_time", DateTime.Now.AddDays(2).ToUniversalTime().ToString(new CultureInfo("en-US")));
createEventParameters.Add("end_time", DateTime.Now.AddDays(2).AddHours(4).ToUniversalTime().ToString(new CultureInfo("en-US")));
createEventParameters.Add("owner", "Balaji Birajdar");
createEventParameters.Add("description", " ( a long description can be used here..)");
//Add the "venue" details for the event
JsonObject venueParameters = new JsonObject();
venueParameters.Add("street", "dggdfgg");
venueParameters.Add("city", "gdfgf");
venueParameters.Add("state", "gfgdfgfg");
venueParameters.Add("zip", "gfdgdfg");
venueParameters.Add("country", "gfdgfg");
venueParameters.Add("latitude", "100.0");
venueParameters.Add("longitude", "100.0");
createEventParameters.Add("venue", venueParameters);
createEventParameters.Add("privacy", "OPEN");
createEventParameters.Add("location", "fhdhdfghgh");
//Add the event logo image
//You can add the event logo too
FacebookMediaObject logo = new FacebookMediaObject()
{
ContentType = "image/jpeg",
FileName = #"C:\DevProjects\O2\o2PriorityFB\o2PriorityFB.Web\Images\logo.jpg"
};
logo.SetValue(System.IO.File.ReadAllBytes(logo.FileName));
createEventParameters["#file.jpg"] = logo;
JsonObject resul = fb.Post("/me/events", createEventParameters) as JsonObject;
return resul["id"].ToString();
}
You need to include a valid access token in the request. Also, I would recommend upgrading to V6 of the Facebook C# SDK. For the version you are using though you need to pass the access token into the constructor of FacebookWebClient as follows:
var fb = new FacebookWebClient("valid_facebook_access_token");

Resources