HybridAuth - continue script after authentication and get result - oauth

I have a facebook login function where I instantiate Hybrid_Auth and the user is authenticated:
$oauth = new Hybrid_Auth( $config );
//go to facebook
$provider = $oauth->authenticate('Facebook');
//continue script?
$profile = $provider->getUserProfile();
die(var_dump($profile));
(as in the example here (configuration & usage) hybridauth.github.io/hybridauth/userguide )
But how is the script supposed to continue where it left off, after the
"->authenticate('Facebook')"?
In all the examples I have seen, a large part seems to be implicit information that is left out, and not being explained.
On "->authenticate", the user is redirected to facebook and then redirected back to a specific url. I have specified a redirect URI in facebook developers, like:
https://myweb.com/fbauth/authenticate?hauth.done=Facebook
and I have a "base_url" in the config array, which I guess is the url that the user returns to after login. I pointed it to the same function where I do the authentication:
'base_url' => 'https://myweb.com/fbauth/authenticate',
So after authentication the function starts again from the beginning, and if it has the "authenticate" slug, I try to run: Hybrid_Endpoint::process(); but this results in a 404. But I would rather have resumed from after the authentication so I can get the result of $profile. How is this supposed to be handled, and how can I get the result? I use Laravel by the way.

Related

How to apply SSO with an existing login screen and a trusted second website

We use IdentityServer3 (IdSvr3) for authorization/authentication. We want to offer the ability for our end user (or resource owner: RO) to log in (log through) to a second trusted website (site B) without login in to site B also, after they have already logged in to an initial website (site A). Site B administers a different set of resources for the RO. It is important that the RO is not redirected to the IdSvr3 login/consent screen. A possible approach I found so far is: inside site A an access token is created by calling RequestResourceOwnerPasswordAsync (passing username and password plus scope = "openid ..."). This access token is send to site B with which the RO can be authenticated. Site B retrieves the user info by calling the connect/userinfo endpoint. I want to know if this is a correct approach/flow. We assume that the RO will always enter site A first, not site B.
Thanks in advance for taking your time to think with me about this.
what you can do here is to send a authorize request to identity server for Site B Scope and request id_token or reference token. Make sure while sending the authorize request to idsrv you are using prompt=none, this way you will get the access_token without showing a consent to the user again if the user is already logged-in to site A.
Below example is doing the same from a JS file. In Site A you can refer to this script file and execute the script using IIFE.
function getIdentityServerURL() {
var url = global.appSettings.identityServerURL
+ "/connect/authorize?client_id=siteB&response_type=id_token token&redirect_uri="
+ global.appSettings.siteBUrl + "/Main/SsoCallback&scope=siteBscope openid email roles&prompt=none&nonce="
+ genNonce();
return encodeURI(url);
}
The code above will redirect you to SsoCallback page where you can create a virtual iframe and post the token back to site B after reducing the result from authorize request. Refer to code below.
<script type="text/javascript">
var identityresult = window.location.hash.split('&').reduce(function (result, item) {
var parts = item.split('=');
result[parts[0]] = parts[1];
return result;
}, {});
window.parent.postMessage(identityresult, '*');
your script can listen to postmessage event. Hope this helps.

Attempting to log in using Google account in cfoauth tag

I am trying to login using the <cfoauth> tag, but am not able to do so. It is showing
Error: invalid_request
Below is my code.
<cfoauth
type = "google"
clientid = "*****************es7t0r6qc"
secretkey = "**************tSF97WncM5ix9jtvD200"
result = "result"
scope="https://www.googleapis.com/auth/plus.me"
redirecturi = "http://192.168.9.126:8088/bootstrap-blog-template/tpl/cfoauth.cfm"
>
Please help.
The problem seems to be related to redirecturi. You need to provide an existing and valid URL of the page on which you want to redirect to after authentication.
For example if local URL of the page you are testing the code is http://localhost:8500/cfbuster/login.cfm , then redirecturi can be same page i.e. http://localhost:8500/cfbuster/login.cfm or another page http://localhost:8500/cfbuster/doLogin.cfm.
Apart from this, the redirecturi you wish to set, should be saved in Google Developers Consele >> API Manager >> Credentials screen under Authorized redirect URIs. In my case it is http://localhost:8500/cfbuster/test.cfm
In case the redirecturi passed is non existing or not saved in the API Authorized redirect URIs screen we get following error message:
Note 1: The redirecturi Must have a protocol. Cannot contain URL fragments or relative paths. Cannot be a public IP address.
Note 2: https://www.googleapis.com/auth/plus.login is the recommended login scope. The https://www.googleapis.com/auth/plus.me scope is not recommended as a login scope because, for users who have not upgraded to Google+, it does not return the user's name or email address.

What is the best way to dynamically specify the redirect url for OAuth strategies in passport.js?

I have setup my facebook auth per passportjs docs:
var passport = require('passport')
, FacebookStrategy = require('passport-facebook').Strategy;
passport.use(new FacebookStrategy({
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
callbackURL: "http://www.example.com/facebook/callback"
},
function(accessToken, refreshToken, profile, done) { ... });
}
));
app.get('/login/facebook', passport.authenticate('facebook'))
.get('/facebook/callback', passport.authenticate('facebook', {successRedirect: '/', failureRedirect: '/login'}));
All this works fine. However, there are cases (such as token expiration) when I want to automatically redirect the user to the page that the user was on before initiating the login request. So I tried to plumb a query string param through the login request (from client to server to facebook and back). But I cant see a way to specify that in the callbackURL.
Furthermore, when I tried hard-coding some context param to the config callbackURL (eg: "http://www.example.com/facebook/callback?redir=lastUserPage") I get an OAuth parse error. Interestingly enough, Facebook does respond correctly with the access code as well as the redir param, but it fails with OAUTH exception:
FacebookTokenError: Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request
at Strategy.parseErrorResponse (C:\Sources\node_modules\passport-facebook\lib\strategy.js:198:12)
at Strategy.OAuth2Strategy._createOAuthError (C:\Sources\node_modules\passport-facebook\node_modules\passport-oauth2\lib\strategy.js:345:16)
at C:\Sources\node_modules\passport-facebook\node_modules\passport-oauth2\lib\strategy.js:171:43
at C:\Sources\node_modules\passport-facebook\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:177:18
at passBackControl (C:\Sources\node_modules\passport-facebook\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:124:9)
at IncomingMessage.<anonymous> (C:\Sources\node_modules\passport-facebook\node_modules\passport-oauth2\node_modules\oauth\lib\oauth2.js:143:7)
at IncomingMessage.emit (events.js:117:20)
at _stream_readable.js:943:16
at process._tickCallback (node.js:419:13)
Note that I had this working using WIF before. I don't see any security concerns with passing additional query string parameters through the OAuth process..
Any idea how I can get past this?
I'm not sure how to do what you're asking, but for your desired end goal you could:
Save a cookie before authenticating
Authenticate the user
on the resulting callback page, check for the cookie and redirect if present.
Wouldn't this work just as easily?

Facebook OAuth: custom callback_uri parameters

I'd like to have a dynamic redirect URL for my Facebook OAuth2 integration. For example, if my redirect URL is this in my Facebook app:
http://www.mysite.com/oauth_callback?foo=bar
I'd like the redirect URL for a specific request be something like this, so that on the server, I have some context about how to process the auth code:
http://www.mysite.com/oauth_callback?foo=bar&user=6234
My redirect gets invoked after the authorization dialog is submitted, and I get back an auth code, but when I try to get my access token, I'm getting an OAuthException error back from Facebook. My request looks like this (line breaks added for clarity):
https://graph.facebook.com/oauth/access_token
?client_id=MY_CLIENT_ID
&redirect_uri=http%3A%2F%2Fwww.mysite.com%2Foauth_callback%3Ffoo%3Dbar%26user%3D6234
&client_secret=MY_SECRET
&code=RECEIVED_CODE
All of my parameters are URL-encoded, and the code looks valid, so my only guess is that the problem parameter is my redirect_uri. I've tried setting redirect_uri to all of the following, to no avail:
The actual URL of the request to my site
The URL of the request to my site, minus the code parameter
The URL specified in my Facebook application's configuration
Are custom redirect URI parameters supported? If so, am I specifying them correctly? If not, will I be forced to set a cookie, or is there some better pattern for supplying context to my web site?
I figured out the answer; rather than adding additional parameters to the redirect URL, you can add a state parameter to the request to https://www.facebook.com/dialog/oauth:
https://www.facebook.com/dialog/oauth
?client_id=MY_CLIENT_ID
&scope=MY_SCOPE
&redirect_uri=http%3A%2F%2Fwww.mysite.com%2Foauth_callback%3Ffoo%3Dbar
&state=6234
That state parameter is then passed to the callback URL.
If, for any reason, you can't use the option that Jacob suggested as it's my case, you can urlencode your redirect_uri parameter before passing it and it will work, even with a complete querystring like foo=bar&morefoo=morebar in it.
I was trying to implement a Facebook login workflow against API v2.9 following this tutorial. I tried the solutions described above. Manuel's answer is sort of correct, but what I observed is url encoding is not needed. Plus, you can only pass one parameter. Only the first query parameter will be considered, the rest will be ignored. Here is an example,
Request a code via https://www.facebook.com/v2.9/dialog/oauth?client_id={app-id}&redirect_uri=http://{url}/login-redirect?myExtraParameter={some-value}
You'd get a callback for your url. It will look like http://{url}/login-redirect?code={code-from-facebook}&myExtraParameter={value-passed-in-step-1}. Note that facebook would make a callback with myExtraParameter. You can extract the value for myExtraParameter from callback url.
Then you can request access token with https://graph.facebook.com/v2.9/oauth/access_token?client_id={app-id}&client_secret={app-secret}&code={code-from-facebook}&redirect_uri=http://{url}/login-redirect?myExtraParameter={value-extracted-in-step-2}
Additional parameter passed in step 1 after the first query parameter will be ignored. Also make sure to not include any invalid characters in your query parameter (see this for more information).
You're best off specifying a unique callback for each oAuth provider, /oauth/facebook, /oauth/twitter etc.
If you really want the same file to respond to all oAuth requests, either include it in the individual files or setup a path that will call the same file on your server using .htaccess redirects or something similar: /oauth/* > oauth_callback.ext
You should set your custom state parameter using the login helper as such:
use Facebook\Facebook;
use Illuminate\Support\Str;
$fb = new Facebook([
'app_id' => env('FB_APP_ID'),
'app_secret' => env('FB_APP_SECRET'),
'default_graph_version' => env('FB_APP_VER'),
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = [
'public_profile',
'user_link',
'email',
'read_insights',
'pages_show_list',
'instagram_basic',
'instagram_manage_insights',
'manage_pages'
];
$random = Str::random(20);
$OAuth2Client = $fb->getOAuth2Client();
$redirectLoginHelper = $fb->getRedirectLoginHelper();
$persistentDataHandler = $redirectLoginHelper->getPersistentDataHandler();
$persistentDataHandler->set('state', $random);
$loginUrl = $OAuth2Client->getAuthorizationUrl(
url('/') . '/auth/facebook',
$random,
$permissions
);
Hey if you are using official facebook php skd then you can set custom state param like this
$helper = $fb->getRedirectLoginHelper();
$helper->getPersistentDataHandler()->set('state',"any_data");
$url = $helper->getLoginUrl($callback_url, $fb_permissions_array);

Twitter O-Auth Callback url

I am having a problem with Twitter's oauth authentication and using a callback url.
I am coding in php and using the sample code referenced by the twitter wiki, http://github.com/abraham/twitteroauth
I got that code, and tried a simple test and it worked nicely. However I want to programatically specify the callback url, and the example did not support that.
So I quickly modified the getRequestToken() method to take in a parameter and now it looks like this:
function getRequestToken($params = array()) {
$r = $this->oAuthRequest($this->requestTokenURL(), $params);
$token = $this->oAuthParseResponse($r);
$this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']);
return $token;
}
and my call looks like this
$tok = $to->getRequestToken(array('oauth_callback' => 'http://127.0.0.1/twitter_prompt/index.php'));
This is the only change I made, and the redirect works like a charm, however I am getting an error when I then try and use my newly granted access to try and make a call. I get a "Could not authenticate you" error. Also the application never actually gets added to the users authorized connections.
Now I read the specs and I thought all I had to do was specify the parameter when getting the request token. Could someone a little more seasoned in oauth and twitter possibly give me a hand? Thank You
I think this is fixed by twitter by now or you might have missed to provide a default callback url in your application settings, which is required for dynamic callback url to work as mentioned by others above.
Any case, I got this working by passing the oath_callback parameter while retrieving the request token. I am using twitter-async PHP library and had to make a small tweak to make the library pass the callback url.
If you are using twitter-async, the change is below:
modified getRequestToken and getAuthenticateURL functions to take callback url as parameter
public function getRequestToken($callback_url = null)
{
$params = empty($callback_url) ? null : array('oauth_callback'=>$callback_url);
$resp = $this->httpRequest('GET', $this->requestTokenUrl, $params);
return new EpiOAuthResponse($resp);
}
public function getAuthenticateUrl($callback_url = null)
{
$token = $this->getRequestToken($callback_url);
return $this->authenticateUrl . '?oauth_token=' . $token->oauth_token;
}
And pass the callback url from your PHP code.
$twitterObj->getAuthenticateUrl('http://localhost/twitter/confirm.php');
#Ian, twitter now allows 127.0.0.1 and has made some other recent changes.
#jtymann, check my answer here and see if it helps
Twitter oauth_callback parameter being ignored!
GL
jingles
even me to was getting 401 error.. but its resolved..
during registering your application to twitter you need to give callback url...
like http://localhost:8080.
i have done this using java...
so my code is: String CallbackURL="http://localhost:8080/tweetproj/index.jsp";
provider.retrieveRequestToken(consumer,CallbackURL);
where tweetproj is my project name
and index.jsp is just one jsp page...
Hope this may helps u...
After the user authorizes the application on twitter.com and they return to your callback URL you have to exchange the request token for an access token.
Twitter does not honor the oauth_callback parameter and will only use the one specified in the registered application settings.
It also doesn't allow for 127.0.0.1 or localhost names in that callback, so I've setup http://dev.twipler.com which is setup for 127.0.0.1 in DNS so you can safely use;
http://dev.twipler.com/twitter_prompt/index.php

Resources