I am using Worklight 6.0 and in this case testing with iOS7.
I'm trying to setup saml 2.0 SSO with Worklight and I seem to have succeeded, but I don't know how it works... At first, I have my app attempt to access my url like this:
WLJQ.ajax({
url: 'url.com',
type: 'GET',
xhrFields: {
withCredentials: true
},
success: function(data, status, xhr) {
console.log(data);
},
error: function(result) {
console.log("error");
console.log(result);
}
});
The request goes to success and returns me the url of the login page, which is correct because I haven't authenticated yet, but it does not display the login (as I intended).
Next I click a button to display a Native page (iOS) which is a UIWebView of url.com. This displays the login page via:
WL.NativePage.show('LoginController', backFromNativeLoginPage, params);
I log in successfully and see the contents of url.com that I expect. Then I return back to the non-native app via:
[NativePage showWebView:0];
Now that I'm back in the non-native code, I sent the same request above and I expect for it not to return the contents of url.com, but rather the login page because I have no headers attached to my request and I think the non-native code shouldn't have any knowledge of the cookies I may have made in the UIWebView.
My question is how does this work? Does my non-native part of worklight have knowledge of all the cookies that were created in the native code's UIWebView?
Let me start by saying my answer is partly based on speculation, but I think this is whats happening:
Since your Native page is using the a WebView and Cordova is also using the WebView, any headers and cookies that your Native page is using will be visible when you return from native since cookies are shared across differet UIWebViews.
If your native page was using the native URL request methods or some third party / open source mechanism for connecting to your backend server, then I would think that your non-native page would not be able to see the headers and cookies.
Related
I am using Auth0 to authenticate users by redirecting them to facebook.
But the problem I am facing is that if a user types in incorrect account credentials the first time and succeeds on the second attempt the redirect does not happen, instead it takes me to "Oops!, something went wrong" page with the following message:
"invalid_request: You probably pressed the back button or there is some issue with cookies, since we couldn't find your session. Try logging in again from the application and if the problem persist contact the administrator."
EDIT: I am using the below Auth0Lock code on the client side.
var lock = new Auth0Lock('<%= auth0.clientId %>', '<%= auth0.domain %>', {
//redirect mode
auth: {
redirectUrl: '<%= auth0.callback %>',
responseType: 'code',
params: {
scope: 'openid' // Learn about scopes: https://auth0.com/docs/scopes
}
},
autoclose: true,
theme: {
logo: 'https://xxxxxx/logo_orange.jpg'
},
languageDictionary: {
title: "test"
}
});
lock.on("unrecoverable_error",function(err) {
console.log(err);
});
lock.on("authorization_error",function(err) {
console.log(err);
});
Once I select Login with facebook I am redirected to facebook url that looks something like link
There if I enter the email/password incorrectly the first time the page refreshes and on the second try if I succeed,instead of taking me back to my app the auth0 generic error page => doc shows up with the error I mentioned at the top.On the server side passport seems to correctly authenticate the user.
PS: Chrome is taking me to a login page which has a login form on top and center but firefox just has login at the center of the page.For chrome if I use the top login form and has a failed login attempt on second successful attempt I am taken to my facebook page i.e no redirect happens.
There's at least one issue and that one is a Facebook problem. Their login page is showing two login forms:
The TOP form has an action equal to:
https://www.facebook.com/login.php?login_attempt=1&lwv=100
while the CENTER one has:
/login.php?login_attempt=1&next=https://www.facebook.com/v2.4/dialog/oauth?redirect_uri=https%3A%2F%2Flogin.eu.auth0.com%2Flogin%2Fcallback&state=[state]&response_type=code&client_id=[client_id]&ret=login&logger_id=1bf0be0d-4b64-43a6-b112-79a30100fa5b&lwv=100
This means that submitting the top form does not maintain enough information to be able to return back to your application. Now, there's still the issue of the Auth0 generic page being shown, but that one I'm unable to reproduce. If you think it's worthwhile, then do upload an HAR for review, even one where you strip all cookies might help.
Update:
Looked at the HAR, the second issue seems to be caused by an authentication request to Facebook that does not pass through Auth0. There's a request to your application, but that one does not complete an then there's this second request that will trigger the Auth0 error page.
Expected flow:
https://test.auth0.com/authorize
https://www.facebook.com/dialog/oauth
https://www.facebook.com/login.php (user authenticates here)
https://www.facebook.com/v2.8/dialog/oauth
https://test.auth0.com/login/callback
https://localhost:8080/callback
What's causing the error generic page, before your localhost request completes another request is issued:
https://www.facebook.com/v2.8/dialog/oauth
https://test.auth0.com/login/callback (generic error page shown here)
The error is caused because https://test.auth0.com/login/callback is called without first going through https://test.auth0.com/authorize to setup the authentication transaction state.
Given the request to your application localhost is marked as incomplete I would start looking in your code to see if there's any reason for that request to not complete.
I have read a number of questions and answers, including this one on StackOverflow and none works. My question to all responses I have seen are 'does it work in Safari?'.
I am trying to get this to work with Safari. It works on Chrome and Firefox fine. But in Safari the login screen just freezes and I get the "Unsafe JavaScript attempt to access frame with URL" log message.
I have a canvas app. I want to log the user in and redirect them to a page once they have logged in. I am trying to redirect directly after login. I have tried
setting window.top.location to a facebook url (with some data passed to a signed request as the all_data argument)
setting window.location to a URL with the same domain as my app.
subscribing to the auth.login event and putting the redirect there
putting the redirect in the callback to login
None of these works for Safari. I'm starting to think that there's no way to do it.
function doSomething()
{
FB.login(
function(loginResponse)
{
if (loginResponse.authResponse)
{
window.top.location = "my url"
}
},
{
scope:"some,scope"
}
);
}
}
In response to Nitzan Tomer, here is the equivalent code which doesn't work with Safari but does work with others:
function myThing()
{
FB.login(function(loginResponse)
{
if (loginResponse.authResponse)
{
FB.api('/me', function(response)
{
window.location = "http://my_app.com?x=" + response.xyz;
});
}
},
{
scope:"scopes"
}
);
}
This is not much of a solution to your problem, but more of a "workaround", though it still uses window.top.location but not from a callback so maybe it will work (I'm just not sure where the callback is executed, since it's the fb sdk that executes it, maybe they call it from the fb iframe inside your iframe).
Instead of using client side authentication, you can use the server side flow.
The entire process is happening on the top window, since it starts by you redirecting the user to the oauth dialog using window.top.location.
When the process ends facebook redirects the user to your redirect_uri, and there you can simply redirect the user where ever you want.
I hope this will help.
Also, you should be aware that in the Facebook Platform Policies it states:
13 . The primary purpose of your Canvas or Page Tab app on Facebook must not be to simply redirect users out of the Facebook experience
and onto an external site.
It turns out the problem was occurring slightly earlier in the login process and the callback never got called. I did set a breakpoint in the callback (which wasn't called) but I thought the breakpoint might not work for some reason (perhaps because it was being executed in the context of another window).
Anyway, the problem was that the channel file (which the docs seem to suggest are optional) wasn't working properly, and this caused a problem with Safari but not with other browsers.
Has anyone been able to figure out how to authenticate an external web site to post to a facebook app's page (wall)?
We have an external rails site, and all I'm looking to do is post to our facebook app's page whenever a new resource is created. I'm so confused right now with all these tokens and expirations!!!
Ex. I can manually visit:
https://www.facebook.com/dialog/oauth?client_id=(our client id)&redirect_uri=(our redirect uri)&scope=manges_pages,publish_stream&response_type=token
(no parenthesis)
to get the account access token, but this approach is manual and it it works only if I go through my browser and I'm signed into FB (so it's using cookies). How can I automate the authenthientication process for my external web app?
I would try to use a Cross-Domain AJAX GET request to the URL (with parameters). This will allow the request to utilize the current user's cookies. jQuery is fairly reasonable for this type of situation. $.ajax(); using JSONP should do it.
Something like this:
$.ajax({
type: 'GET',
url: 'https://www.facebook.com/dialog/oauth',
data: {
client_id: '(our client id)',
redirect_uri: '(our redirect uri)',
scope: 'manges_pages',
publish_stream: '',
response_type: 'token',
format: 'jsonp'
},
dataType: 'jsonp',
success: function(data)
{
// Do stuff.
}
});
EDIT:
Should be noted that I haven't ever done this with Facebook's API specifically. In doing a little digging, I don't know if this is possible to do with just a GET request:
https://developers.facebook.com/docs/reference/api/
Seems you need some kind of authentication to happen on the server-side before you can publish to their API.
For our iPhone native application we have a URL : example://
On the iPhone if I type this URL (example://) in safari it automatically opens up my application.
From my "regular" website I have a link which when the user clicks it opens the application. The problem is that if the application is not installed on the iPhone it throws "Unable to open" error.
So before rendering the link on my "regular" site I need to check if the app is installed, one solution is to make an Ajax call and check for status code:
$.ajax({
type: 'POST',
url: 'example://',
complete: function (transport) {
if (transport.status == 200) {
alert('Success');
} else {
alert(transport.status);
alert('Failed');
}
}
});
But this code is always returning a status code "0".
Is there a way to find out from the web if the native iPhone app is installed?
If u are referring to Mobile Safari, you're out of luck. There's no documented public API that I know of that can do this. Mobile Safari is sandboxed away from the OS.
If it's in a webview within an app, u can request the URL and let the webview delegate talk to the native app / query the handling of example://. Otherwise, no way the browser can know existence of any installed app.
The context:
I'm actually developing a small web app (C#/MVC2). Users are going to use their iPhones (and probably Android phones in the future) to access it.
At the moment it's quite simple (it just shows some info and reports from our customer's ERP), and I decided to give a try at creating local webapp that the users could add to their iPhones, so that they had an icon for it and, most importantly, most files are locally cached, so that only the relevant data is obtained using json from the server.
The problem:
To authenticate users, a small form asks for username and password, and sends them to the server via ajax, which in turn validates the user and sets the authcookie. If the app is executed in Safari, everything works ok, but if it's executed locally (that is, in Mobile Safari directly from an icon), the server validates correctly the user, but this validation is lost when the next ajax call to recover data is made.
Does this mean that session cookies are not supported by Mobile Safari in webapps? I'm doing it wrong?
And most importantly: What's the best way to authenticate users in a local webapp that access remote data?
I'm not quite sure about what do you mean by local webapp. I assume that it's an HTTP web server running on localhost.
If that's the case, you need some protocol to communicate between http://localhost and http://yourwebsite.com, and that protocol should help localhost authenticate user via yourwebsite.com. I think OAuth might be what you're looking for.
The first time the user access your local webapp, he will be redirected to yourwebsite.com for the authentication. After that, yourwebsite.com will bring him back with an OAuth token. After verifying that token is valid from yourwebsite.com, localhost can serve user on its own.
(I realise I'm very late to this question, but anyway…)
Mobile Safari employs a slightly different web engine to that used in "home-screen apps" (i.e. web pages that you bookmark as self-contained icons on the iOS home screen).
Perhaps the issue you're seeing with cookies comes from that, rather than in Mobile Safari per se? I guess it's easy enough to test: if the app all works OK in Mobile Safari, and not from a home screen icon, there's your answer.
As an alternative take, rather than relying on authentication in the on-line version of the app, another approach that may work for you / your organisation is using the app in an unauthenticated state, but over a VPN for mobile workers? (This will still work OK as an offline web app).
Instead of using a cookie can't you have a ajax call to login that just returns the "authcookie"-value. The value can be saved using localStorage or similar.
http://dev.w3.org/html5/webstorage/
Later when you want to fetch something you can send this value to the server using a custom header (X-authentication or similar) or just append it as a GET-variable to the url.
Your best bet :
http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
To access a protected resource, the client includes the access token
in the Authorization header of the HTTP request
Login :
var loginData = {
grant_type: 'password',
username: ...,
password: ...
};
$.ajax({
type: 'POST',
url: '/Token',
data: loginData
}).done(function (data) {
// Cache the access token in session storage.
sessionStorage.setItem(tokenKey, data.access_token);
});
Second request:
// If we already have a bearer token, set the Authorization header.
var token = sessionStorage.getItem(tokenKey);
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: 'GET',
url: 'api/values/1',
headers: headers
}).done(function (data) {});
If you don't plan to use Web API, you must generate your own token and put it in every request data