Microsoft Office 365 Task or Todo php api authorization - php

I want to implement some workflows, they should add some tasks to Microsoft todo app.
They have a rest api. I try to access the oauth. But have wrong return url. And I don't want to have a browser application it should be only a php script running in background.
I tried this:
$url = oAuthService::getLoginUrl("http://localhost/microsoftToDoTest/auth.php");
header("location:".$url);
class oAuthService {
private static $clientId = "";
private static $clientSecret = "";
private static $authority = "https://login.microsoftonline.com";
private static $authorizeUrl = '/common/oauth2/authorize?client_id=%1$s&redirect_uri=%2$s&response_type=code';
private static $tokenUrl = "/common/oauth2/token";
public static function getLoginUrl($redirectUri) {
$loginUrl = self::$authority.sprintf(self::$authorizeUrl, self::$clientId, urlencode($redirectUri));
error_log("Generated login URL: ".$loginUrl);
return $loginUrl;
}
}
What would be the correct way to authorize with php on the microsoft services?
Thanks in advance

Looking to your code and the documentation I would assume you need to request a token to create a valid session. Then supply that token over an url in a cookie with a session ID.
Route::get('/authorize', 'AuthController#gettoken');
Now in their documentation microsoft supplies this:
public function signin()
{
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Initialize the OAuth client
$oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => env('OAUTH_APP_ID'),
'clientSecret' => env('OAUTH_APP_PASSWORD'),
'redirectUri' => env('OAUTH_REDIRECT_URI'),
'urlAuthorize' => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
'urlAccessToken' => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
'urlResourceOwnerDetails' => '',
'scopes' => env('OAUTH_SCOPES')
]);
// Generate the auth URL
$authorizationUrl = $oauthClient->getAuthorizationUrl();
// Save client state so we can validate in response
$_SESSION['oauth_state'] = $oauthClient->getState();
// Redirect to authorization endpoint
header('Location: '.$authorizationUrl);
exit();
}
https://learn.microsoft.com/en-us/outlook/rest/php-tutorial microsoft probably uses the same way all around office365. Hopefully this will help you implement the right code.

Related

Docusign - API connect JWT - consent_required

My goal: get a token to send a digital signature request (server to server)
Environnement : PHP, Symfony - Demo environment
Here is the error I am receiving when running the following code: Error : "consent_required"
My code :
class ServiceSignature
{
private $container;
private $accessToken;
private $accountId;
private $signerName;
private $signerEmail;
private $fileNamePath;
private $basePath;
private $appPath;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->accountId = "dc295354-xxxx-xxxx-xxxx-f2e3a8813b1e";
$this->basePath = 'https://demo.docusign.net/restapi';
$this->appPath = $_ENV["FOLDER_UPDATE"];
$this->accessToken = "";
$this->private_key_path = "../docusign_private.pem";
$this->private_key = file_get_contents($this->private_key_path);
$this->cle_integration = "bdfeaf70-xxxx-xxxx-xxxx-8a2ed57eb7ef";
$this->audience = "account-d.docusign.com";
$this->permission_scopes= "signature impersonation";
$this->token = $this->getToken();
}
public function getToken()
{
$current_time = time ();
$_token = [
"iss" => $this->cle_integration,
"sub" => $this->accountId,
"aud" => $this->audience,
"scope" => $this->permission_scopes,
"nbf" => $current_time,
"exp" => $current_time + 60*1000
];
$jwt = JWT::encode($_token, $this->private_key, 'RS256');
$headers = ['Accept' => 'application/json'];
$data = ['grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt];
$body = Unirest\Request\Body::form($data);
$response = Unirest\Request::post("https://{$this->audience}/oauth/token", $headers, $body);
if (strpos($response->raw_body, '<html>') !== false) {
throw new Exception("An error response was received!\n\n");
}
$json = $response->body;
dump($json);
die();
}
}
Thank you in advance
The problem is likely that the User GUID that you've supplied has not yet granted consent.
Follow this guide for obtaining consent and you should be good to go.
An excerpt:
When an application authenticates to perform actions on behalf of a
user, that user will be asked to grant consent for the set of scopes
(sets of permissions) that the application has requested unless they
have previously already granted that consent.
To begin authentication and obtain consent, your application redirects
the user's browser to the DocuSign authorization URI. Note that this
is not a standard GET request and cannot be directly sent by the
application. Instead, the user's browser is redirected to an
authorization request URI and the request is sent from there to the
account server.

How to access outlook address book using outlook rest api

I would like to access the global address book of an organization through outlook rest api
I was able to implement the Single Sign-on part using OAUTH2 but I'm unable to understand how to access the contacts object
I have gone through this
and many other examples but unable to understand how to implement them in PHP
Firstly, if you want to use the rest api to access the outlook contacts, at the moment, Microsoft suggests customers use the Microsoft Graph. For more details, please refer to the document
Secondly, regarding how to get outlook conatcts with php application, you need to use oauth2-client to add Azure AD authentication and get Azure AD access token then call the api to get contacts with the access token. For example, please refer to the following steps to know how to implement it in php web application
Register Azure AD application
Configure app permissions you need for your application
Implement Azure AD authentication with the SDK oauth2-client
a. Create a .env file
OAUTH_APP_ID=YOUR_APP_ID_HERE
OAUTH_APP_PASSWORD=YOUR_APP_PASSWORD_HERE
OAUTH_REDIRECT_URI=<your redirect url>
OAUTH_SCOPES='openid profile offline_access' + <your need outlook permissions>
OAUTH_AUTHORITY=https://login.microsoftonline.com/common
OAUTH_AUTHORIZE_ENDPOINT=/oauth2/v2.0/authorize
OAUTH_TOKEN_ENDPOINT=/oauth2/v2.0/token
b. Get access token
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class AuthController extends Controller
{
public function signin()
{
// Initialize the OAuth client
$oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => env('OAUTH_APP_ID'),
'clientSecret' => env('OAUTH_APP_PASSWORD'),
'redirectUri' => env('OAUTH_REDIRECT_URI'),
'urlAuthorize' => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
'urlAccessToken' => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
'urlResourceOwnerDetails' => '',
'scopes' => env('OAUTH_SCOPES')
]);
$authUrl = $oauthClient->getAuthorizationUrl();
// Save client state so we can validate in callback
session(['oauthState' => $oauthClient->getState()]);
// Redirect to AAD signin page
return redirect()->away($authUrl);
}
public function callback(Request $request)
{
// Validate state
$expectedState = session('oauthState');
$request->session()->forget('oauthState');
$providedState = $request->query('state');
if (!isset($expectedState)) {
// If there is no expected state in the session,
// do nothing and redirect to the home page.
return redirect('/');
}
if (!isset($providedState) || $expectedState != $providedState) {
return redirect('/')
->with('error', 'Invalid auth state')
->with('errorDetail', 'The provided auth state did not match the expected value');
}
// Authorization code should be in the "code" query param
$authCode = $request->query('code');
if (isset($authCode)) {
// Initialize the OAuth client
$oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => env('OAUTH_APP_ID'),
'clientSecret' => env('OAUTH_APP_PASSWORD'),
'redirectUri' => env('OAUTH_REDIRECT_URI'),
'urlAuthorize' => env('OAUTH_AUTHORITY').env('OAUTH_AUTHORIZE_ENDPOINT'),
'urlAccessToken' => env('OAUTH_AUTHORITY').env('OAUTH_TOKEN_ENDPOINT'),
'urlResourceOwnerDetails' => '',
'scopes' => env('OAUTH_SCOPES')
]);
try {
// Make the token request
$accessToken = $oauthClient->getAccessToken('authorization_code', [
'code' => $authCode
]);
return redirect()->route('contacts');
}
catch (League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
return redirect('/')
->with('error', 'Error requesting access token')
->with('errorDetail', $e->getMessage());
}
}
return redirect('/')
->with('error', $request->query('error'))
->with('errorDetail', $request->query('error_description'));
}
}
```
Use the access token With Microsoft Graph SDK. For more details, please refer to the docuemnt
public function mail()
{
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$tokenCache = new \App\TokenStore\TokenCache;
$graph = new Graph();
$graph->setAccessToken($tokenCache->getAccessToken());
$contacts = $graph->createRequest('GET', '/me/contacts/{Id}')
->setReturnType(Model\Contact::class)
->execute();
}
Regarding the details of how to implement it, please refer to the sample
Besides, if you want to call the outlook rest api with php, please refer to the document. But please note that you need to change the app permissions.

Split OAuth php login in 2 functions

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

PHP/Twitter oAuth - Automated Tweets

Im using the following code to read to consumer_key and consumer_secret from config.php, pass it to twitter and retrieve some bits of information back from them.
What the script below attempts to do is 'cache' the request_token and request_secret. So in theory I should be able to reuse those details (all 4 of them to automatically tweet when required).
<?php
require_once('twitteroauth/twitteroauth.php');
require_once('config.php');
$consumer_key = CONSUMER_KEY;
$consumer_secret = CONSUMER_SECRET;
if (isset($_GET["register"]))
{
// If the "register" parameter is set we create a new TwitterOAuth object
// and request a token
/* Build TwitterOAuth object with client credentials. */
$oauth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$request = $oauth->getRequestToken();
$request_token = $request["oauth_token"];
$request_token_secret = $request["oauth_token_secret"];
// At this I store the two request tokens somewhere.
file_put_contents("request_token", $request_token);
file_put_contents("request_token_secret", $request_token_secret);
// Generate a request link and output it
$request_link = $oauth->getAuthorizeURL($request);
echo "Request here: " . $request_link . "";
die();
}
elseif (isset($_GET["validate"]))
{
// This is the validation part. I read the stored request
// tokens.
$request_token = file_get_contents("request_token");
$request_token_secret = file_get_contents("request_token_secret");
// Initiate a new TwitterOAuth object. This time we provide them with more details:
// The request token and the request token secret
$oauth = new TwitterOAuth($consumer_key, $consumer_secret,
$request_token, $request_token_secret);
// Ask Twitter for an access token (and an access token secret)
$request = $oauth->getAccessToken();
// There we go
$access_token = $request['oauth_token'];
$access_token_secret = $request['oauth_token_secret'];
// Now store the two tokens into another file (or database or whatever):
file_put_contents("access_token", $access_token);
file_put_contents("access_token_secret", $access_token_secret);
// Great! Now we've got the access tokens stored.
// Let's verify credentials and output the username.
// Note that this time we're passing TwitterOAuth the access tokens.
$oauth = new TwitterOAuth($consumer_key, $consumer_secret,
$access_token, $access_token_secret);
// Send an API request to verify credentials
$credentials = $oauth->oAuthRequest('https://twitter.com/account/verify_credentials.xml', 'GET', array());
// Parse the result (assuming you've got simplexml installed)
$credentials = simplexml_load_string($credentials);
var_dump($credentials);
// And finaly output some text
echo "Access token saved! Authorized as #" . $credentials->screen_name;
die();
}
?>
When i run /?verify&oauth_token=0000000000000000 - It works however trying to resuse the generated tokens etc... I get a 401
Here is the last bit of code where I attempt to reuse the details from Twitter combined with my consumer_key and consumer_secret and get the 401:
require_once('twitteroauth/twitteroauth.php');
require_once('config.php');
// Read the access tokens
$access_token = file_get_contents("access_token");
$access_token_secret = file_get_contents("access_token_secret");
// Initiate a TwitterOAuth using those access tokens
$oauth = new TwitterOAuth($consumer_key, $consumer_key_secret,
$access_token, $access_token_secret);
// Post an update to Twitter via your application:
$oauth->OAuthRequest('https://twitter.com/statuses/update.xml',
array('status' => "Hey! I'm posting via #OAuth!"), 'POST');
Not sure whats going wrong, are you able to cache the details or do i need to try something else?
You can't store the OAuth tokens in cache and to more than 1 request with it, as OAuth is there to help make the system secure, your "oauth_token" will contain some unique data, this token will only be able to make one call back to twitter, as soon as the call was made, that "oauth_token" is no longer valid, and the OAuth class should request a new "oauth_token", thus making sure that every call that was made is secure.
That is why you are getting an "401 unauthorized" error on the second time as the token is no longer valid.
twitter is still using OAuth v1 (v2 is still in the draft process even though facebook and google already implemented it in some parts)
The image below describes the flow of the OAuth authentication.
Hope it helps.
A while ago I used this to connect to twitter and send tweets, just note that it did make use of some Zend classes as the project was running on a zend server.
require_once 'Zend/Service/Twitter.php';
class Twitter {
protected $_username = '<your_twitter_username>';
protected $_token = '<your_twitter_access_token>';
protected $_secret = '<your_twitter_access_token_secret>';
protected $_twitter = NULL;
//class constructor
public function __construct() {
$this->getTwitter();
}
//singleton twitter object
protected function getTwitter() {
if (null === $this->_twitter) {
$accessToken = new Zend_Oauth_Token_Access;
$accessToken->setToken($this->_token)
->setTokenSecret($this->_secret);
$this->_twitter = new Zend_Service_Twitter(array(
'username' => $this->_username,
'accessToken' => $accessToken,
));
$response = $this->_twitter->account->verifyCredentials();
if ($response->isError()) {
throw new Zend_Exception('Provided credentials for Twitter log writer are wrong');
}
}
return $this->_twitter;
}
//send a status message to twitter
public function update( $tweet ) {
$this->getTwitter()->status->update($tweet);
}
}
In your second script, it looks like you aren't setting the Consumer Key and Consumer Secret when you create your TwitterOAuth instance.
// Initiate a TwitterOAuth using those access tokens
$oauth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token, $access_token_secret);

Best way to use Zend_Oauth_Consumer without cookies and without session

I am developing gadget with tech requirements: "no Cookie, no Session".
I have the following code:
<?php
class LinkedIn
{
private $options;
private $consumer;
private $client;
private $token;
public function __construct($params)
{
// set Zend_Oauth_Consumer options
$this->options = array(
'version' => '1.0',
'localUrl' => $params['localUrl'],
'callbackUrl' => $params['callbackUrl'],
'requestTokenUrl' => 'https://api.linkedin.com/uas/oauth/requestToken',
'userAuthorizationUrl' => 'https://api.linkedin.com/uas/oauth/authorize',
'accessTokenUrl' => 'https://api.linkedin.com/uas/oauth/accessToken',
'consumerKey' => $params['apiKey'],
'consumerSecret' => $params['secretKey']
);
// instanciate Zend_Oauth_Consumer class
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Oauth_Consumer');
$this->consumer = new Zend_Oauth_Consumer($this->options);
}
public function connect()
{
// Start Session to be able to store Request Token & Access Token
session_start ();
if (!isset ($_SESSION ['ACCESS_TOKEN'])) {
// We do not have any Access token Yet
if (! empty ($_GET)) {
// SECTION_IF
// But We have some parameters passed throw the URL
// Get the LinkedIn Access Token
$this->token = $this->consumer->getAccessToken ($_GET, unserialize($_SESSION ['REQUEST_TOKEN']));
// Store the LinkedIn Access Token
$_SESSION ['ACCESS_TOKEN'] = serialize ($this->token);
} else {
// SECTION_ELSE
// We have Nothing
// Start Requesting a LinkedIn Request Token
$this->token = $this->consumer->getRequestToken ();
// Store the LinkedIn Request Token
$_SESSION ['REQUEST_TOKEN'] = serialize ($this->token);
// Redirect the Web User to LinkedIn Authentication Page
$this->consumer->redirect ();
}
} else {
// We've already Got a LinkedIn Access Token
// Restore The LinkedIn Access Token
$this->token = unserialize ($_SESSION ['ACCESS_TOKEN']);
}
// Use HTTP Client with built-in OAuth request handling
$this->client = $this->token->getHttpClient($this->options);
}
}
It's working perfect. But REQUEST_TOKEN stored in SESSION. How can I put it to query string in SECTION_ELSE, and get it back in SECTION_IF? Thanks for all the advice.
The key point is that your system needs to:
1. persist the OAuth tokens between user requests to your server, and
2. tie them to a specific user.
Using a session, whose id comes from either a cookie or from the querystring, is one way to do that.
But if sessions are off the table, then you need some other way to identify the current user and store his OAuth tokens.
If you are truly working in a no-session environment, then how do you even know who the user is? Basic Auth? In the absence of user authentication on your side, I don't see how you'll be able associate OAuth tokens to specific users.

Categories