Never really worked with OAuth, trying to implement it now, I want to get access token and profile data from google and facebook. Using Xamarin.Auth.
With Facebook there're no problems, I specify "http://www.facebook.com/connect/login_success.html" as redirect url and after I login it goes back to the activity I was before.
However with Google it's not as smooth - couldn't find any similar to facebook login success pages, somewhere found suggestion to use "https://www.googleapis.com/plus/v1/people/me" - added it to redirect url white list, however after sign in I would get "Redirect_url_mismatch" A native application: application nameaccording to their documentation I should use "my.package.name:" and again I added that to redirect url white list, attempted to sign in, this time after sign in screen I get to second screen where I need to confirm read permissions and after that I get very short error something like "com.my.package:/?oauthparameterX=value1...." and get redirected to permission screen again.
Here's my complete OAuth2Authenticator:
var auth = new OAuth2Authenticator(
clientId: SocialIds.GooglePlusId,
clientSecret: SocialIds.GooglePlusSecret,
scope: OAuthUrl.GoogleScope,
authorizeUrl: new Uri(OAuthUrl.GoogleAuthorize),
redirectUrl: new Uri("https://www.googleapis.com/plus/v1/people/me"),
accessTokenUrl: new Uri("https://accounts.google.com/o/oauth2/token"),
getUsernameAsync: null);
auth.AllowCancel = false;
urls:
public static string GoogleAuthorize = "https://accounts.google.com/o/oauth2/auth";
public static string GoogleScope = "https://www.googleapis.com/auth/userinfo.email";
public static string GoogleRedirect = "https://www.googleapis.com/plus/v1/people/me";
public static string GoogleUserInfo = "https://www.googleapis.com/oauth2/v1/userinfo?access_token={0}";
In the above listed code, you are not giving the redirect uri instead you are giving the scope of google api. The purpose of redirect uri is to recieve the response from google api after authorization. The response should be a code. This response code is used for accessing the access_token,refresh_token, id_token etc. So you have to recieve this code in your project side.For this purpose , the redirect uri is used.
Go to your google console, create project, add credentials, then you will be redirect to a page conatains,
You can find the authorized redirect url. Give the url , then configure your code with new redirect url . Everything will be fine after this.
Related
I am using Android Web View in my Xamarin Project to perform third party authentication. Once the login is successful I need to extract the authentication cookies. This cookies I am storing in persistent storage and then I am using them for passing to subsequent requests.
For example:
Android App >(opens) webview > Loads (idp provider) url > User provides credentials and saml request is sent to my backend server > backend server validates saml and returns authentication cookies.
It returns two cookies.
Now everything works fine. And in OnPageFinished method of the WebClient of webview I am trying to extract the cookies using the method.
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
var handler = OnPageCompleted;
var uri = new Uri(url);
AllowCookies(view);
var cookies = CookieManager.Instance.GetCookie(url);
var onPageCompletedEventArgs = new OnPageCompletedEventArgs { Cookies = cookies, Url = uri.AbsolutePath, RelativeUrl = uri.PathAndQuery, Host = uri.Host };
handler?.Invoke(this, onPageCompletedEventArgs);
}
private void AllowCookies(WebView view)
{
CookieManager.Instance.Flush();
CookieManager.AllowFileSchemeCookies();
CookieManager.SetAcceptFileSchemeCookies(true);
CookieManager.Instance.AcceptCookie();
CookieManager.Instance.AcceptThirdPartyCookies(view);
CookieManager.Instance.SetAcceptCookie(true);
CookieManager.Instance.SetAcceptThirdPartyCookies(view, true);
}
The problem is, I am able to get just one cookie(wc_cookie_ps_ck
), I am unable to see the other authentication cookie(.AspNetCore.Cookies
).
Here's how the cookies appear in browser.
Please note that in postman and in chrome browser both the cookies appear.
But in android webview only cookie with name ".AspNetCore.Cookies" is not appearing at all.
As per Java document,"When retrieving cookies from the cookie store, CookieManager also enforces the path-match rule from section 3.3.4 of RFC 2965 . So, a cookie must also have its “path” attribute set so that the path-match rule can be applied before the cookie is retrieved from the cookie store."
Since both of my cookies have different path, is that the reason the one with path set as "/project" is not appearing?
After days and days of finding the answer to the question. I finally have found an answer.
I did remote debugging of the webview with the desktop chrome and I found out that all the cookies that I needed were present in the webview.
However the method,
var cookies = CookieManager.Instance.GetCookie(url);
doesn't return the cookie which has the same site variable set.
This looks like a bug from Xamarin Android. I have already raised an issue in Xamarin Android github.
In the xamarin android github issue I have mentioned the steps to reproduce.
For me, the workaround to resolve the issue was to set the samesite cookie varibale off in my asp.net core back end project.
As follows:
In order to configure the application cookie when using Identity, you can use the ConfigureApplicationCookie method inside your Startup’s ConfigureServices:
// add identity
services.AddIdentity<ApplicationUser, IdentityRole>();
// configure the application cookie
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
});
Link for the above solution mentioned. Here.
I have followed the following guide for google sign in https://learn.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/authentication/oauth and for reference I took this example https://developer.xamarin.com/samples/xamarin-forms/WebServices/OAuthNativeFlow/.
As per the steps I created Android and iOS client ID but for android I didnt get any redirect URL option.
public static class Constants
{
public static string AppName = "TestingLogin";
// OAuth
// For Google login, configure at https://console.developers.google.com/
public static string iOSClientId = "clientID";
public static string AndroidClientId = "clientID";
// These values do not need changing
public static string Scope = "https://www.googleapis.com/auth/userinfo.email";
public static string AuthorizeUrl = "https://accounts.google.com/o/oauth2/auth";
public static string AccessTokenUrl = "https://www.googleapis.com/oauth2/v4/token";
public static string UserInfoUrl = "https://www.googleapis.com/oauth2/v2/userinfo";
// Set these to reversed iOS/Android client ids, with :/oauth2redirect appended
public static string iOSRedirectUrl = "<insert IOS redirect URL here>:/oauth2redirect";
public static string AndroidRedirectUrl = "http://weblogin.bestokleen.com/googleindex.aspx:/oauth2redirect";
}
please check the image for reference. I added my android client ID but I couldnt find any redirect url for android on console.developers.google.com. So i created a web client and registered a redirect url which is working in web browser so I used that particular redirect URL in my project But got same error.
Now I tried placing Web Client ID and redirectURL instead of Android cliend ID but still getting the same error as shown in the pic.
From your first link:
Therefore, a complete example of a redirect URL utilizing a custom URL scheme is com.googleusercontent.apps.<client ID>:/oauth2redirect
Anyway, the Android Client ID looks like <What I called Client ID>.apps.googleusercontent.com. So chances might be, that you'll succeed by using the reversed Android Client ID for the redirect URL.
Anyway, I succeeded using <my package name>:/oauth2redirect (something like com.yourcompany.yourapp:/oauth2redirect) both for Android and iOS, but don't ask me if there have been any further steps involved.
EDIT
From the first link, too (see here)
The DataSchemes property of the IntentFilter must be set to the reversed client identifier that's obtained from the Android client id for the project on Google API Console.
That supports my presumption made upon the other information.
I'm developing an application using Xamarin.Android.
I need to enable login with Facebook and Google and I choose to use the Xamarin.Auth component.
I got it work with facebook but I have some issue with Google.
This is my code:
var auth = new OAuth2Authenticator (
clientId: "myId.apps.googleusercontent.com",
clientSecret: "mysecred",
scope: "openid",
authorizeUrl: new Uri ("https://accounts.google.com/o/oauth2/auth"),
redirectUrl: new Uri ("myredirect:oob"),
accessTokenUrl: new Uri ("https://accounts.google.com/o/oauth2/token"),
getUsernameAsync: null
);
activity.StartActivity (auth.GetUI (activity));
auth.Completed += (sender, e) => {
Console.WriteLine (e.IsAuthenticated);
};
Is this way the Google Activity is displayed, and I can insert my Username and password. But when I click the google login button I get a message like this:
google auth please copy this code switch to your application and paste it there [code]
What I have to do with that code? I just need to get the user name/lastname/email/id.
Thanks a lot!
Bellow steps worked for me.
1.register in google developer console as webapplication instead of installed application(android)* provide the redirect url with valid url ("http://abcd.com/xyz.aspx") same should be used in the application code.
2.on authentication complete it will return access_token
3.by using the access_token make the REST request to get user complete information (https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + accessTokenValue + “.)
4.Deserialize the json response to get information in object.
check the source code :http://appliedcodelog.blogspot.in/2015/08/login-by-google-account-integration-for.html
i'm trying to connect twitter for android. so I have downloaded the source from github. but i got a message, which is
<error>Desktop applications only support the oauth_callback value 'oob'</error>
but i already have defined it. 'public static final String REST_CALLBACK_URL = "hywtest://hywtwitter";'
i change callback_url to 'oob', i can come close to twitter, but when change a page, show pin number, and there's nothing happens.
of course, i have changed manifest too.
<data
android:host="hywtwitter"
android:scheme="hywtest" />
please help me!
You have to provide a callback URL in your Twitter Application Page in Application Details where twitter return after successful authentication.
You need to provide a placeholder callback URL on your application record on dev.twitter.com -- this placeholder allows you to perform callback-based auth with a dynamically supplied callback on the oauth/request_token step.
I am posting to user's wall using following code using restFB.
String myAccessToken = null;
String appId="my app id ......";
String appSecret="my app secret";
// facebook user id of the user on whose wall to post
String userId="user id ...";
DefaultFacebookClient dfc = new DefaultFacebookClient();
AccessToken accessToken = dfc.obtainAppAccessToken(appId,appSecret);
myAccessToken = accessToken.getAccessToken();
FacebookClient facebookClient = new DefaultFacebookClient(myAccessToken);
FacebookType publishMessageResponse = facebookClient.publish(userId+"/feed", FacebookType.class, Parameter.with("message", "test"));
System.out.println("Published message ID: " + publishMessageResponse.getId());
All is working fine.
But now I want to include user's facebook first name in the post. Is there any way to do so? I dont want to generate yet another request to facebook for getting the username, as I am already generating 2 requests for getting user id(from redirect url). Is there any mechanism that graph api itself replaces some kind of tag in the post text with user name.
E.g I send the following text to post on user wall:
#username# is doing something...
And it is replaced by facebook graph api
Mark is doing something....
I dont want to generate yet another request to facebook for getting the username, as I am already generating 2 requests for getting user id(from redirect url).
No you can't. You have to make the request to fetch the name. /me?fields=name
But why does it matter, it'll take very less time to query this.