I am trying to use the Admin-paterson oauth library for PHP to connect to slack
(https://github.com/adam-paterson/oauth2-slack)
When I run the sample code:
include("slack-vendor/autoload.php");
include("slacker/src/Provider/Slack.php");
$provider = new \AdamPaterson\OAuth2\Client\Provider\Slack([
'clientId' => $$slackid,
'clientSecret' => $slacksecret,
'redirectUri' => $returnURL,
]);
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 to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// 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
$team = $provider->getResourceOwner($token);
// Use these details to create a new profile
printf('Hello %s!', $team->getName());
} catch (Exception $e) {
// Failed to get user details
exit('Oh dear...');
}
// Use this to interact with an API on the users behalf
echo $token->getToken();
}
I get an error back from slack saying :
Invalid permissions requested
Requested scopes cannot be blank
I tried adding a "scope" to the call like this:
$provider = new \AdamPaterson\OAuth2\Client\Provider\Slack([
'clientId' => $slackid,
'clientSecret' => $slacksecret,
'redirectUri' => $returnURL,
'scope' => 'channels:write,groups:write,team:read'
]);
but it still returns the same error.
When I look at the url the scope field is blank
what do I need to do to send scope to the server?
Add your scope in getAuthorizationUrl() method like this
$authUrl = $provider->getAuthorizationUrl([
'scope' => 'channels:write'
]);
use the scope as defined in https://api.slack.com/apps/ in your App, under OAuth, e.g. 'scope' => 'users.profile:read'
Related
I am trying to consume Zoom's API using PHP and Oauth2. I was able to connect to the aplication and get the token using the generic lib oauth2-client. But, when I try to make a simple request, I get an error, saying that the email is missing. This is my code:
<?php
session_start();
require __DIR__ . '/vendor/autoload.php';
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => 'meuclientid',
'clientSecret' => 'meuclientsecret',
'redirectUri' => 'http://localhost/teste_oauth2/',
'urlAuthorize' => 'https://zoom.us/oauth/authorize',
'urlAccessToken' => 'https://zoom.us/oauth/token',
'urlResourceOwnerDetails' => 'https://api.zoom.us/v2/users/me'
]);
// If we don't have an authorization code then get one
if (!isset($_GET['code'])) {
$authorizationUrl = $provider->getAuthorizationUrl();
// Get the state generated for you and store it to the session.
$_SESSION['oauth2state'] = $provider->getState();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
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.
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
$request = $provider->getAuthenticatedRequest(
'GET',
'https://api.zoom.us/v2/users/email',
$accessToken,
['email' => 'meuemail#gmail.com']
);
var_dump($provider->getResponse($request));
die('aqui');
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
// Failed to get the access token or user details.
echo $e->getMessage();
exit;
}
}
?>
As you can see, I am passing the email on the request. But I am getting the Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: GET https://api.zoom.us/v2/users/email resulted in a 400 Bad Request response: {"code":300,"message":"Email is required."}
Can anyone help me?
You are using
['email' => 'meuemail#gmail.com']
which is not allowed in the function $provider->getAuthenticatedRequest
You need to pass it with the existing URL:
$request = $provider->getAuthenticatedRequest(
'GET',
'https://api.zoom.us/v2/users/email?email=meuemail#gmail.com',
$accessToken
);
I hope this helps..!!
Zoom API Reference: https://marketplace.zoom.us/docs/api-reference/zoom-api/users/useremail
OAuth Reference: https://github.com/thephpleague/oauth2-client
Need some help,
Using Wohali OAuth2 Client then Restcord to get actual content from the user logged.
But for some reason, i can't get it to list the roles for the user logged in.
Says "Message: There was an error executing the listGuildMembers command: Client error: GET https://discordapp.com/api/v6/guilds/{guild_id}/members?limit=1 resulted in a 401 UNAUTHORIZED response:"
The documentation is a bit lacking and i have spent a number of hours trying to get it sorted out.
use RestCord\DiscordClient;
$provider = new \Wohali\OAuth2\Client\Provider\Discord([
'clientId' => '{client_id}',
'clientSecret' => '{client_secret}',
'redirectUri' => '{redirect_uri}'
]);
$options = ['state' => 'CUSTOM_STATE', 'scope' => ['identify', 'email', 'guilds']];
if (!isset($_GET['code'])) {
// Step 1. Get authorization code
$authUrl = $provider->getAuthorizationUrl($options);
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authUrl);
// 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 {
// Step 2. Get an access token using the provided authorization code
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
}
$user = $provider->getResourceOwner($token);
$client = new DiscordClient(['token' => $token->getToken(), 'tokenType' => 'OAuth']);
$roles = $client->guild->listGuildRoles(['guild.id' => {guild_id}]);
var_dump($roles);
I have removed the clientId, secret, guild id and such but they are valid, since the example on auth from Wohali works and shows my info when logged in.
Thanks in advance for any tips / help / ideas.
You can view the response codes on the official discord docs:
https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#http-http-response-codes
401 means your token is bad/missing
I'm trying to use djchen's Fitbit wrapper for thephpleague code to get Fitbit OAuth2 access for my website. It can be found here: https://github.com/djchen/oauth2-fitbit
This was working perfectly for a while and now suddenly, I'm getting "Forbidden" error. I can't remember changing any code on the login.php file. Any ideas as to why this would happen?
Here is my main code:
<?php namespace djchen\OAuth2\Client\Provider;
require __DIR__.'/vendor/autoload.php';
require __DIR__.'/vendor/oauth2-fitbit-master/src/Provider/Fitbit.php';
require __DIR__.'/vendor/oauth2-fitbit-master/src/Provider/FitbitUser.php';
use djchen\Oauth2\Client\Provider\Fitbit;
use djchen\Oauth2\Client\Provider\FitbitUser;
$provider = new Fitbit([
'clientId' => '****',
'clientSecret' => '****',
'redirectUri' => '****'
]);
ob_start();
ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/var/php_sessions'));
session_start();
// If we don't have an authorization code then get one
if (!isset($_GET['code'])) {
echo "going down this path \n";
// Fetch the authorization URL from the provider; this returns the
// urlAuthorize option and generates and applies any necessary parameters
// (e.g. state).
$authorizationUrl = $provider->getAuthorizationUrl();
// Get the state generated for you and store it to the session.
$_SESSION['oauth2state'] = $provider->getState();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
echo $_SESSION['oauth2state'] . " is the oauth2state saved \n";
echo $_GET['state'] . " is the get_state \n";
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
try {
// Try to get an access token using the authorization code grant.
$accessToken = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]);
echo "still going...";
// The provider provides a way to get an authenticated API request for
// the service, using the access token; it returns an object conforming
// to Psr\Http\Message\RequestInterface.
$request1 = $provider->getAuthenticatedRequest(
Fitbit::METHOD_GET,
Fitbit::BASE_FITBIT_API_URL . '/1/user/-/profile.json',
$accessToken,
['headers' => [Fitbit::HEADER_ACCEPT_LANG => 'en_US'], [Fitbit::HEADER_ACCEPT_LOCALE => 'en_US']]
// Fitbit uses the Accept-Language for setting the unit system used
// and setting Accept-Locale will return a translated response if available.
// https://dev.fitbit.com/docs/basics/#localization
);
// Make the authenticated API request and get the parsed response.
$response1 = $provider->getParsedResponse($request1);
//eventually will set variables here...
$deviceSpecificID=$response1['user']['encodedId'];
$firstName=$response1['user']['firstName'];
$lastName=$response1['user']['lastName'];
//making repeat request to get more data
$request2 = $provider->getAuthenticatedRequest(
Fitbit::METHOD_GET,
Fitbit::BASE_FITBIT_API_URL . '/1/user/-/activities/date/2017-09-23.json',
$accessToken,
['headers' => [Fitbit::HEADER_ACCEPT_LANG => 'en_US'], [Fitbit::HEADER_ACCEPT_LOCALE => 'en_US']]);
$response2=$provider->getParsedResponse($request2);
$stepsToday=$response2['summary']['steps'];
$stepGoal=$response2['goals']['steps'];
$todaysDate=date("Y-m-d");
//add variables to the session
$_SESSION['loggedin']=True;
$_SESSION['device']="fitbit";
$_SESSION['deviceSpecificID']=$deviceSpecificID;
$_SESSION['firstName'] = $firstName;
$_SESSION['lastName']=$lastName;
$_SESSION['activityArray']=$activityArray;
$_SESSION['steps']=$stepsToday;
$_SESSION['dailyGoal']=$stepGoal;
$_SESSION['todaysDate']=$todaysDate;
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
// Failed to get the access token or user details.
exit($e->getMessage());
}
}
?>
I'm fairly confident that I've deduced the error is being thrown when running the line:
$accessToken = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]);
Any ideas why the error of "Forbidden" would show up? I'm not getting any php errors on my cgi_error log in my webhost's control panel.
Thank you so much in advance. I'm near pulling my hair out, and I'm not sure where to go from here.
Brett
I am using an OAuth plugin in my php application. All works well when I use all the code in one function. But I want split the OAuth call, and the OAuth token treatment. I try to create a global var for the provider object, but it doesn't work. I always have an error with the $provider object.
This is the function I have for the moment :
function login(){
$provider = new Stevenmaguire\OAuth2\Client\Provider\Microsoft([
'clientId' => 'myclientid',
'clientSecret' => 'mysecret',
'redirectUri' => 'https://mywebsite'
//'redirectUri' => 'https://mywebsite/loginMicrosoft' //The url where I want use the token
]);
if (!isset($_GET['code'])) {
$authUrl = $provider->getAuthorizationUrl();
$this->Session->write('oauth2state', $provider->getState());
// This is the part I want put in the function loginMicrosoft. All else if and else
} elseif (empty($_GET['state']) || ($_GET['state'] !== $this->Session->read('oauth2state'))) {
$this->Session->destroy();
exit('Invalid state');
} else {
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// Use this to interact with an API on the users behalf
$this->log( $token->getToken());
}
}
//This is the function where I want put the elseif and else treatment
function loginMicrosoft (){
}
Thanks for your help.
EDIT : I also try to put my provider object in session, but I have the message "Call to a member function getAccessToken() on a non object"
EDIT 2 : After unsuccessfully tried, I keep all the OAuth code in the same function
I am following the docs from link below:
https://developers.google.com/+/mobile/android/sign-in#enable_server-side_api_access_for_your_app
Specifically the part that says:
If you do not require offline access, you can retrieve the access token and send it to your server over a secure connection. You can obtain the access token directly using GoogleAuthUtil.getToken() by specifying the scopes without your server's OAuth 2.0 client ID. For example:
I retrieve the access token like this:
accessToken = GoogleAuthUtil.getToken(
AuthenticatorActivity.this,
Plus.AccountApi.getAccountName(Common.mGoogleApiClient),
"oauth2:https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.login email"
);
After I retrieve the access token I send it to a web server, on the web server i can see that it's a valid access token by calling
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$_POST['google_access_token']
The request above returns the android apps client id, it also returns the users email correctly.
The problem is that when I try to run $client->authenticate($_POST['google_access_token']); I get an exception with the message: "invalid_grant: Incorrect token type".
To prevent getToken caching I always invalidate the token in android app:
if (accessToken != null && !accessToken.isEmpty()) {
GoogleAuthUtil.invalidateToken(AuthenticatorActivity.this, accessToken);
}
Here's the php code:
if (!isset($_POST['google_access_token'])) {
throw new Exception('missing google_access_token');
}
$client = new \Google_Client();
$client->setApplicationName("GiverHub");
$client->setClientId($this->config->item('google_client_id'));
$client->setClientSecret($this->config->item('google_client_secret'));
$client->setDeveloperKey($this->config->item('google_developer_key'));
$client->setRedirectUri($this->config->item('google_redirect_uri'));
$client->setScopes([
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.me',
'email',
]);
try {
$client->authenticate($_POST['google_access_token']); // if i remove this the rest of the code below works! ...
$reqUrl = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$_POST['google_access_token'];
$req = new \Google_Http_Request($reqUrl);
$io = $client->getIo();
$response = $io->executeRequest($req);
$response = $response[0];
$response = json_decode($response, true);
if ($response === null) {
throw new Exception('Failed to check token. response null');
}
if ($response['issued_to'] !== '466530377541-s7cfm34jpf818gbr0547pndpq9songkg.apps.googleusercontent.com') {
throw new Exception('Invalid access token. issued to wrong client id: '. print_r($response, true));
}
if (!isset($response['user_id'])) {
throw new Exception('Missing user_id');
}
if (!isset($response['email'])) {
throw new Exception('Missing email');
}
/** #var \Entity\User $user */
$user = Common::create_member_google([
'id' => $response['user_id'],
'email' => $response['email'],
'given_name' => '',
'family_name' => '',
]);
$user->login($this->session);
if ($user instanceof \Entity\User) {
echo json_encode( [ 'success' => true, 'user' => $user ] );
} else {
echo json_encode( [ 'success' => false, 'msg' => $user ] );
}
} catch(Exception $e) {
echo json_encode(['success' => false, 'msg' => $e->getMessage()]);
}
The above code works if i remove the $client->authenticate(); line ... The problem is that I can't get the given_name / family_name etc .. only email / google_user_id from the tokeninfo ...
Any thoughts about why the key works for tokeninfo but not for authenticate?
I have tried many different variations of the scopes .. both on the server side and the android side ..
The $client->authenticate() method doesn't quite do what you're trying to do. It takes a one-time code from an earlier OAuth transaction and exchanges it for the access token. In your case - you're saying you already have the access token.
You should be able to call $client->setAccessToken() to set the token instead, so it may look something like
$client->setAccessToken($_POST['google_access_token']);
This is the solution I came up with after user158443 suggested I use $client->setAccessToken();
// first json_encode the access token before sending it to $client->setAccessToken();
$json_encoded_access_token = json_encode([
'access_token' => $_POST['google_access_token'],
'created' => time(), // make up values for these.. otherwise the client thinks the token has expired..
'expires_in' => time()+60 // made up a value in the future...
]);
// and then set it
$client->setAccessToken($json_encoded_access_token);
// and then get userinfo or whatever you want from google api !! :)
$oauth2 = new \Google_Service_Oauth2($client);
$user_info = $oauth2->userinfo->get();
NOTE: it's probably not smart to "emulate" the expires_in and created that i just did if you are in production ... You should probably call tokeninfo first and get the expires time from there...
NOTE: I still have no idea how to get a refresh token for this... but I don't need one for my use case..