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.
Related
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.
I have made an application for android with cordova, the homepage is in local and calls to web services through jQuery. The app has a plugin to view a PDF.
Now we want to see a PDF, but to see the pdf need to be log on the server. The login process done with jQuery and it works. Once we log on the server we can call services that require login.
The problem is that we want to retrieve a PDF that requires login, but the http session is not shared from jquery to cordova plugin (or webview). The request on the server is like a not log user.
We tried to recover PDFs do not need login and it works.
The plugin used is based on http://call-me-early.blogspot.com.es/2013/03/android-webview-download-pdf-generated.html
¿Any ideas?
We have tried to retrieve the pdf with jquery and pass the array of bytes to the plugin but does not work.
Another idea is to move the contents of the jquery's cookie to the plugin, but we can not get this cookie
Fixed. What we do is capture the cookie in the call (in success) that creates the session on the server. We keep the cookie locally and then send it to open the PDF plugin, this plugin adds the cookie to the call that makes the native part.
JS part:
success: _.bind(function(data, textStatus, request){
var header = request.getAllResponseHeaders();
console.log("header: "+header);
var match = header.match(/(Set-Cookie|set-cookie|Set-cookie): (.+?);/);
console.log("match: "+match);
if(match!==undefined && match!==null && match.length>=3){
console.log("CON COOKIE");
console.log("COOKIE: "+match[2]);
localStorage.setItem("miCookie",match[2]);
}
},this),
Plugin call
function callShowPdfPluginAndroid( param ){
require(['utils'], function(utils) {
utils.showLoading();
return cordova.exec( function(){utils.hideLoading();},
function(error){utils.hideLoading();nativePluginErrorHandler(error);},
"NativeBridgeAndroid",
"ShowPdf",
[param,localStorage.getItem("miCookie")]);
});
}
Native:
URL u = new URL(params[0]);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setRequestProperty("Cookie",cookie);
c.setDoOutput(true);
c.connect();
I'm developing an Android application which requires Flickr API integration. In previous days, I was able to successfully complete the oauth process. But now its not working, and I strongly believe it happend after flickr APIs changed from http:// to https://
Let me explain the situation..
I'm following the steps explained in Flickr API Doc
As a result of the call to http://www.flickr.com/services/oauth/request_token API, I'm successfully receiving the oauth_token.
After this step, I'm presenting Flickr authorization page in a webview with the url specified in API doc (which is somthing similar like, https://www.flickr.com/services/oauth/authorize?oauth_token=72157626737672178-022bbd2f4c2f3432, and of-course, with the oauth_token which I received in the previous step)
Few days before this call was working when I'm using http:// instead of https://. But now, both http:// and https:// are not working. The page is displaying the login screen, but after successful login, the page is not redirecting to the grant access page, instead it is just redirecting to the Flickr Home page. And hence, I'm unable to grant access and unable to receive the oauth_verifier.
Hope I'm well explaining the situation which I'm facing now. But in short, Flickr Login for my application is not working, and I'm running out of time... :(
So, Geeks, Please give some light on the issue...
--Thanks in advance.
I got the same problem. I was using the connection in a WebView and my code was using the "http" protocol in the request.
I could resolve the issue by first using the "https" protocol for the authentification URL. As you say just doing that did not work. So I change the call of the url that was in the WebView and used the ACTION_VIEW intent and it worked.
Calling :
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(AuthentificationPath)));
Don't forget to implement the OnResume() function of your Activity to get the data of the returned intent.
Of course it is just a workaround but it does the job if you have to be fast.
Hope it helps!
Still the issue is there, After oauth Flickr is not redirecting to grant_access page. But I need to get the oauth process successfully completed in my on-going project, as soon as possible. So I have done a workaround to solve the issue.
To solve the 'not redirecting' issue, I have done a little bit change in my WebView's WebViewClient implementation. It's nothing great, but just redirecting to authorize page again, after successful login.
Authorize URL Example : https://www.flickr.com/services/oauth/authorize?oauth_token=72157626737672178-022bbd2f4c2f3432
So, given below is the detailed implementation of WebViewClient:
mAuthWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
showProgressDialog();
/** TODO: This part should be deleted after flickr fixes the oauth redirection issue */
if(url.endsWith("flickr.com/")) {
mAuthWebView.loadUrl("https://www.flickr.com/services/oauth/authorize?oauth_token=72157626737672178-022bbd2f4c2f3432");
return;
}
/* After successful login the redirected url will contain a parameter named 'oauth_verifier' */
if (url.indexOf("oauth_verifier=") > -1) {
/* Get the 'oauth_verifier' parameter from url and do next steps */
performLoginSuccess();
}
}
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (url.contains(_my_redirect_url_) && !url.contains("oauth_verifier=")) {
/* User not authenticated our app */
finish();
} else if (!url.contains("oauth_verifier=")) {
killProgressDialog();
}
}
});
After loading the authorization url, the web view will take the user to login page, and after user successfully loged into Flickr, with web vew client implementation we are again loading the authorization url, to present the grant access page.
mAuthWebView.loadUrl("https://www.flickr.com/services/oauth/authorize?oauth_token=72157626737672178-022bbd2f4c2f3432");
I know, this is not the right way to do this...
Any better solutions are always welcome.... :)
I have an android application using a webview on which the user has to log in with username and password before being redirected to the page i would like to scrape data off with jsoup. Since the jsoup thread would be a different session the user would have to login again.
Now i would like to use the cookie received from the webview to send with the jsoup request to be able to scrape my data.
The cookie is being synced with cookiesyncmanager with following code. This is basically where I am stuck cause i dont know how to read out the cookie nor how to attach it to the jsoup request. Please help? :)
public void onPageFinished(WebView view, String url) {
CookieSyncManager.getInstance().sync();
The jsoup scrape I am doing after the user has logged in with something like this:
doc = Jsoup.connect("https://need.authentication.com").get();
Elements elements = doc.select("span.tabCount");
Element count = elements.first();
Log.d(TAG, "test"+(count));
I'm not an android developer but maybe you can try something like this:
final String url = "https://need.authentication.com";
// -- Android Cookie part here --
CookieSyncManager.getInstance().sync();
CookieManager cm = CookieManager.getInstance();
String cookie = cm.getCookie(url); // returns cookie for url
// ...
// -- JSoup part here --
// Jsoup uses cookies as "name/value pairs"
doc = Jsoup.connect("https://need.authentication.com").header("Cookie", cookie).get();
// ...
I hope this helps a bit, but as i said before: im no android developer (and code isn't tested!)
Here's some documentation:
CookieManager
CookieSyncManager
Jsoup Connection
Now i try to Implement Twitter Integration in android using twitter4j library.Few months back I successfully implemented this using a dummy call back url like "PicPuzzle://tkxel".
But now Twitter changes its scheme and now not allow to create application with dummy URL.
Now the problem is after authentication It redirect to callbackurl But not return to application.
I specify the same url in application and registration page. I refered Problem in Callback in Twitter in Android and How I can call back in Android using OAuth for Twitter?. But these solutions are now not working because now twitter not allow to create application with dummy URL. Please help me to solve this problem.
Follow below steps:
Go to Twitter Apps: https://apps.twitter.com/
Then, Go to your app.
Go to Settings Tab
In section "Callback URLs", add the below line:
twittersdk://
Click button "Update Settings" at the bottom. That's it.
Hope this works!
Create your own WebViewClient subclass.
Override shouldOverrideUrlLoading(WebView view, String url) method.
In shouldOverrideUrlLoading(), check if url.startsWith(YOUR_CALLBACK_URL) is true.
If true, retrieve "oauth_verifier" parameter from the URL and return true (true from shouldOverrideUrlLoading() prevents the WebView instance from loading the URL).
Get an access token using the value of the parameter obtained in the step 4.
Your application can get control back from the WebView instance after the step 4.
If the above steps sound cumbersome, try TwitterOAuthView. Its usage is very simple. Just call
view.start(CONSUMER_KEY, CONSUMER_SECRET, CALLBACK_URL, true, listener);
and receive the result via TwitterOAuthView.Listener interface defined as below.
void onSuccess(TwitterOAuthView view, AccessToken accessToken);
void onFailure(TwitterOAuthView view, TwitterOAuthView.Result result);
If true is given to TwitterOAuthView.start() method as the forth argument, TwitterOAuthView does not access the callback URL, and I think this behavior is what you want to implement. The source code, TwitterOAuthView.java, may be of help.