I am building a web application with OAUTH authentication to Azure AD.
What I mean is, you log into my application via your Azure AD / Office365 account.
After login is succeeded, I match the GUID of the Azure AD user with the user in my Mysql database.
I set in the session information that the user is logged.
I used this howto for the basics of it:
https://kvaes.wordpress.com/2016/10/21/azure-using-php-to-go-all-oauth2-on-the-management-api/
The basics of the code I use for logging a user to my PHP application:
//User is not logged in, try to log in
$provider = new TheNetworg\OAuth2\Client\Provider\Azure([
'clientId' => getsetting('aadsso_clientid'),
'clientSecret' => getsetting('aadsso_secret'),
'redirectUri' => getsetting('aadsso_redirecturl')
]);
if (!isset($_GET['code'])) {
// If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState();
header('Location: '.$authUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
try {
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code'],
'resource' => 'https://graph.windows.net',
]);
} catch (Exception $e) {
exit ("Connection error. Contact the administrator");
}
// Optional: Now you have a token you can look up a users profile data
try {
// We got an access token, let's now get the user's details (AAD login succeeded)
$me = $provider->get("me", $token);
//Some code here LEFT OUT, to find the user in my MySQL database.
$_SESSION['loggedin'] = 1;
$_SESSION['aadguid'] = $me['objectId'];
} catch (Exception $e) {
// Failed to get user details
exit ("Connection error. Contact the administrator");
}
}
That works fine! But, when I set "$_SESSION['loggedin'] = 1;", the user is logged in to the application.
I really want to understand how to make the user log out of my application, when he logs out of his Azure AD/Office365 session. For example, he logs in to my app, goes to outlook.office.com, clicks logout there. When he goes back to my app and tries to load a page, my app should "see" he's logged out of Azure AD.
How to accomplish this, without losing to much performance of my app?
I am quite a rookie in this, but please give me some tips.
This might not be the same code you are using but Microsoft has a sample on PHP how to auth: https://learn.microsoft.com/en-ca/graph/tutorials/php?tutorial-step=3
you will see that somewhere in that example, they implement a signout URL routing for Laravel.
Then in your app registration under Authentication -> there is a section called Logout URL, if you specify a URL there, then if the user logs off of Azure SSO, it will send a call to that logout URL, to potentially execute the logout URL that you implemented. This will kill the token in your app, which should then now no longer have a session?
I know it's not exactly what you're asking in terms of adding it to your code, but please have a look at the example, you may want to test that out.
Related
I am trying to log users out from my website while they are using facebook login.
I am using "Facebook login php sdk v5".
i used fb-callback to log in:
<?php
session_start();
# login-callback.php
require_once 'facebook-sdk-v5/autoload.php';
$fb = new Facebook\Facebook([
'app_id' => 'XXXXXXXXXXXXX',
'app_secret' => 'XXXXXXXXXXXXXX',
'default_graph_version' => 'v2.5',
]);
$helper = $fb->getRedirectLoginHelper();
try {
$accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
if (isset($accessToken)) {
// Logged in!
$_SESSION['facebook_access_token'] = (string) $accessToken;
header('Location: index.php');
// Now you can redirect to another page and use the
// access token from $_SESSION['facebook_access_token']
}
?>
so i guees to check if some one is logged in i just check if the $_SESSION['facebook_access_token'] is set but to log them out do i "manually" put null inside the $_SESSION['facebook_access_token']?
If you paste how you log your users it would be helpful. I will assume you use default example code from facebook (FB) for login with their php sdk. It works sending a request to a RESTful api (from your server to facebook graph api) so theres actually no session (RESTful approach), everything is managed through an access_token. When a user logs in to your site through FB, it passes to your callback URL a response wich contains an access_token field, then you can use that access_token only once, generally to get FB user's profile, then you validate that information to log in your user in your server. Why all this explanation? because you should understand how this process works.
The short answer to this is, you handle the logout manually (Session::destroy() for example), you don't need the FB php sdk for logout
Logging People Out
You can log people out of your app by undoing whatever login status indicator you added, for example deleting the session that indicates a person is logged in. You should also remove the stored access token.
Logging someone out is not the same as revoking login permission (removing previously granted authentication), which can be performed separately. Because of this, build your app so it doesn't automatically force people who have logged out back to the Login dialog.
(THANKS FACEBOOK DOCS)
I programmed a Google Login for my website. The user needs to use his or her specific school gmail. However, I run into a problem. If the user accidentally tries to login with another gmail that isn't his school email, the website warns him "You should be using your school gmail" and brings him back to the login page. However, if he tries to click "Login with Google" again (because ideally he would pick the correct Google email address), the session for his previous Google account is still running and doesn't even give him an option to try his other gmail account. I don't know exactly what to do...do I destroy the session? Does the user have to manually log out? Here is the error handling code.
unset($_SESSION['token']);
$authUrl = $client->createAuthUrl();
echo ("<SCRIPT LANGUAGE='JavaScript'>
window.alert('You need to login with your school Google account.')
window.location.href='http://websitename.com/login';
</SCRIPT>");
If after destroying your session google authentication URL redirects you directly to your redirect file, it is probably because no new google access token has to be assigned. In case you don't need to store and re-use the same access token and want the user to log in every time authenticating with Google, you have to revoke the token after using it.
In order to revoke an access token, you have to execute the following line
$client->revokeToken();
Example code for this behavior would be:
$client->setAccessToken($access_token);
if (!$client->isAccessTokenExpired()) {
try {
$plus = new Google_Service_Plus($client); // starts google profile (plus) service
$me = $plus->people->get('me'); // saves account info
$email = $me->emails[0]->value; // email
$id = $me->id; // id
$name = $me->name->givenName; // name
$surname = $me->name->familyName; // surname
$client->revokeToken();
$user = updateUser($email, $name, $surname, $id, $pic, $shortener); // proprietary function
} catch (Google_Exception $e) {
abortLogin("couldn't check google profile details", true); // proprietary function
}
} else {
abortLogin("invalid token", true); // proprietary function
}
session_destroy();
So I have recently integrated the new Office365 Rest API with PHP and have it working successfully with the Contacts API.
The system will generate the request url and redirect the user back once authentication is complete which works perfectly fine however if you go back to the script it will automatically log you through the process again as Office365 does not force reauthorisation.
Our script currently allows multiple users to sync their accounts with our system however this is only letting one user perform this per browser session.
require_once('./src/Office365_Client.php');
$client = new Office365_Client();
$forward_url = $client->createAuthUrl();
if (isset($_GET['code'])) {
$code = $_GET['code'];
$client->setCode($code);
$responseObj = $client->getTokens();
$access_token = $client->getAccessToken();
$refresh_token = $client->getRefreshToken();
$_SESSION['access_token'] = $access_token;
$_SESSION['instance_url'] = $instance_url;
$icustomer = (isset($_SESSION['icustomer'])) ? $_SESSION['icustomer'] : false;
header("location: " . $_SESSION['redirUrl'] . "?crm=office365&access_token=$access_token&refresh_token=$refresh_token");
//die();
//////////////////////////////////////////////////////////
// LOAD CONTACTS
/////////////////////////////////////////////////////////
//$client->getContactsFolders();
///////////////////////////////////////////////////
} else {
header("location: $forward_url");
}
Ideally it should work as followed:
User visits our website -> We generate Auth URL and the user is redirected to the Login Page for Office365 (They will then to autheticate if previously not done so) -> Once complete this will return them back to our selection screen with their code ready for their access token to be created. If the user wishes to add a different Office365 account they should be able to go through that process again without using a different browser.
Add prompt=login to the authorization request, so:
header("location: $forward_url" . "&prompt=login");
Have you tried logging out? The logout URI is https://login.windows.net/common/oauth2/logout. So you would want to do something like
https://login.windows.net/common/oauth2/logout?post_logout_redirect_uri=<some page in your app>
I'm trying to activate cookies via the facebook login so it doesnt always depend on the session being there but whenever I set sharedSession to true I get a "The page isn't redirecting properly" error page.. Is this the way I'm suppose to make it so the facebook login uses cookies? I'm using the newest code on github for the facebook SDK (downloaded a freshy today) -> https://github.com/facebook/facebook-php-sdk
I'm not using the javascript SDK. and all of the coding below is fired before any headers are sent out. If I take the sharedSession out, it logs me in correctly, but it doesnt store a cookie with the info needed.
Heres the coding I'm using
$facebook = new Facebook(array(
'appId' => $Sets['facebook']['appId'],
'secret' => $Sets['facebook']['appSecret'],
'sharedSession' => true,
// 'trustForwarded' => true
));
$user = $facebook->getUser();
if($user){
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
$user = null;
}
}
// the user is logged into facebook
if($user){
// I register them on my website..
// and then send them to the index page
header('Location: /index.php');
} else {
// they are not registered through facebook
if(isset($_GET['error'])){
// this happens when an error is found
die($_GET['error'].' error');
// header("Location: /login/?error=".urlencode($_GET['error']));
exit;
} else {
// send to facebook to log them in.
$loginUrl = $facebook->getLoginUrl($Sets['facebook']['scope_array']);
// die('sending to '.$loginUrl);
header("Location: ".$loginUrl);
exit;
}
}
You can see I put the die() function before any redirection there, this was for debugging on my end to see if I can figure out where it was failing, but it seems to happen after the user is returned to the website.. I also tried the trustForward => true, but that didnt fix it..
all I'm after is to be able to have the user logged in for a longer period of time, without having to login through facebook everytime they visit the website.
Whats happening is the user is stuck in a loop trying to log into facebook being redirected between facebook and my website because the user is never verified. Again, this ONLY happens when I set 'sharedSession' => true
I'm trying to get the facebook sdk to store a cookie from my website onto the persons computer that tries to login but no cookie is being set.
I get confused by your question. what do you want to achieve:
1) If you want to set store your facebook user_id to cookie, you don't have to do anything. when the oauth process is completed facebook redirect to your "redirect_uri" url, the cookie is set by facebook to a cookie value: fbsr_xxxx (xxxx is your appId)
2) If you want to keep user logged in longer time, you need to set your own session value to determine if the user is logged in or not. in other word, after the facebook oauth flow, your user login status has nothing to do with your facebook session.
BTW: $Users->loginWithOauth, this function has no definition, what's this function for?
the reason is the required permission not granted so eventually it goes to facebook search for the token and comes back.
check for the permission you need.
I'm struggling to find a way to detect if users are not connected to my application, I want to send the activity 'View' an 'Item' which works perfectly fine, but they have to click a login link first, when just reloads the page and they are logged in.
How can I make this happen automatically? How can you check if the user is connected to the app?
I have tried the following code, but users who are not connected just get a blank page.
$facebook = new Facebook($config);
$user_id = $facebook->getUser();
// Check if logged in
if($user_id) {
$params = array(
'ok_session' => 1, // Logged in and connected
'no_user' => 2, // Logged out of facebook
'no_session' => 3, // Logged in but not connected
);
$next_url = $facebook->getLoginStatusUrl($params);
if($next_url == 2 || $next_url == 3){
header('Location: '.$facebook->getLoginUrl(array('scope' => 'publish_stream')));
}
} else {
// Not logged in
header('Location: '.$facebook->getLoginUrl(array('scope' => 'publish_stream')));
}
There doesn't seem to be a function that checks if the user is connected so I made use of the getLoginUrl function.
$user_id is supplied by $user_id = $facebook->getUser();
If we are talking canvas/page tab app here, then the info you’re looking for is in the signed_requestparameter your app gets passed on initial load.
If not – “outside” of Facebook the PHP SDK has no way of knowing if there’s a user visiting your page that has used your app before if there aren’t any cookies set for your domain remaining that say so.
You can use FB.getLoginStatus out of the JS SDK – that will make a cross-domain request to Facebook to see if the user is logged in, and can set the appropriate cookies under your domain that’ll let the PHP SDK take notice on the next request to your server as well.