我目前正在尝试使用Office365 REST API,为此,我需要使用OAuth2机制进行身份验证。到目前为止,非常好。
经过长时间的战斗,我终于设法获取了所述令牌,但我需要获取与令牌一起使用的用户信息(例如他的标识符,电子邮件,姓名等)。
使用沙箱,我需要这样的东西:
我已经尝试通过api.office.com
api:
curl https://api.office.com/discovery/v1.0/me/services -H "Authorization: Bearer <oauth token>" -H "Accept: application/json;odata=verbose"
但我所拥有的是以下内容:
{"error":{"code":"-2147024891, System.UnauthorizedAccessException","message":"Access denied. You do not have permission to perform this action or access this resource."}}
获取所述OAuth令牌的请求基于这些参数(通过HWIOAuthBundle):
<?php
$config = ['authorization_url' => 'https://login.windows.net/%s/oauth2/authorize',
'infos_url' => 'https://outlook.office365.com/api/%s/me',
'access_token_url' => 'https://login.windows.net/%s/oauth2/token',
'application' => 'common',
'api_version' => 'v1.0',
'csrf' => true];
$config['access_token_url'] = sprintf($config['access_token_url'], $config['application']);
$config['authorization_url'] = sprintf($config['authorization_url'], $config['application']);
$config['infos_url'] = sprintf($config['infos_url'], $config['api_version']);
所以任何想法如何获取用户信息(甚至是基本信息)?
由于
- 编辑
我想我明白了。看来https://outlook.office365.com/api/v1.0/me
上的curl请求给出了一个带有MailboxGuid,Id,Alias和GivenName的简单数组:
curl https://outlook.office365.com/api/v1.0/me -X GET -H "Authorization: Bearer <my oauth token>"
给出以下内容(有时会暂停,有时不会......我想我必须继续努力,如果有人可以提出建议,请随意插入)
{"@odata.context":"https://outlook.office365.com/api/v1.0/$metadata#Me",
"@odata.id":"https://outlook.office365.com/api/v1.0/Users('baptiste@wisembly.onmicrosoft.com')",
"Id":"baptiste@wisembly.onmicrosoft.com",
"DisplayName":"Baptiste Clavi\u00e9",
"Alias":"baptiste",
"MailboxGuid":"<snip>"}
它不像沙盒返回的东西那么完整,但它应该给我我需要的东西......
但是...它有时会给我一个暂停,有时它会很好......大约是3/5的比例。任何的想法 ?感谢
P.S:如果您需要知道我如何在azure上配置应用程序,请询问
答案 0 :(得分:2)
您是否查看了令牌请求中返回的身份令牌?这可能包含您想要的所有信息,并且您已经拥有它,因此无需再发出第二个请求。
这里有一个sample(除其他外)解析身份令牌以获取用户的显示名称。查看Office365Service.php中的getUserName
功能:
// Parses an ID token returned from Azure to get the user's
// display name.
public static function getUserName($id_token) {
$token_parts = explode(".", $id_token);
// First part is header, which we ignore
// Second part is JWT, which we want to parse
error_log("getUserName found id token: ".$token_parts[1]);
// First, in case it is url-encoded, fix the characters to be
// valid base64
$encoded_token = str_replace('-', '+', $token_parts[1]);
$encoded_token = str_replace('_', '/', $encoded_token);
error_log("After char replace: ".$encoded_token);
// Next, add padding if it is needed.
switch (strlen($encoded_token) % 4){
case 0:
// No pad characters needed.
error_log("No padding needed.");
break;
case 2:
$encoded_token = $encoded_token."==";
error_log("Added 2: ".$encoded_token);
break;
case 3:
$encoded_token = $encoded_token."=";
error_log("Added 1: ".$encoded_token);
break;
default:
// Invalid base64 string!
error_log("Invalid base64 string");
return null;
}
$json_string = base64_decode($encoded_token);
error_log("Decoded token: ".$json_string);
$jwt = json_decode($json_string, true);
error_log("Found user name: ".$jwt['name']);
return $jwt['name'];
}
答案 1 :(得分:0)
通过查看许多来源......我在这里改进了php office365客户端
https://github.com/mehmetsen80/office365client
假设你有一个这样的配置:
的config.php
<?php
/**
* Created by PhpStorm.
* User: msen
* Date: 3/10/16
* Time: 11:55 AM
*/
global $apiConfig;
$apiConfig = array(
'oauth2_client_id' => '',//assign your own office 365 app client id
'oauth2_secret' => '', // Generate key from Azure Management Portal
'oauth2_redirect' => 'http://website.com/office365client/oauth2.php', //example url
'state' => '45d12e60b-8457-4d99-b20f-cfb612d1a138', //any unquiue key to Check against CSRF attack
'resource' => 'https://outlook.office365.com',
'oauth2_auth_url' => 'https://login.windows.net/common/oauth2/authorize',
'oauth2_token_url' => 'https://login.windows.net/common/oauth2/token',
);
?>
最后你会有这样的代码..
session_start();
$client = new Office365_Client();
$forward_url = $client->createAuthUrl();
$code = $_GET['code'];
if(isset($_GET['code'])) {
$client->setCode($code);
$client->fetchTokens(); //get tokens
$client->fetchJWT();//let's get user info
//put the user token info into sessions
$_SESSION['name'] = $client->getJwt()->getName();//full name of the user
$_SESSION['unique_name'] = $client->getJwt()->getUniqueName();//could be email or id from office365
$_SESSION['tid'] = $client->getJwt()->getTid();//tenant id
}else{
header( 'Location: '.$forward_url ); //redirect automatically on the first page visit, 2nd page visit will get the $code
}
Microsoft告诉我们可以检索哪些用户信息.. https://msdn.microsoft.com/library/office/dn707383.aspx
JWT.php
<?php
/**
* Created by PhpStorm.
* User: msen
* Date: 3/10/16
* Time: 12:04 PM
*/
class JWT
{
private $aud;
private $iss;
private $iat;
private $nbf;
private $exp;
private $ver;
private $tid;
private $amr;
private $oid;
private $upn;
private $puid;
private $sub;
private $given_name;
private $family_name;
private $name;
private $unique_name;
private $appid;
private $appidacr;
private $scp;
private $acr;
public function __construct($jwt_arr){
$this->aud = $jwt_arr['aud'];
$this->iss = $jwt_arr['iss'];
$this->iat = $jwt_arr['iat'];
$this->nbf = $jwt_arr['nbf'];
$this->exp = $jwt_arr['exp'];
$this->ver = $jwt_arr['ver'];
$this->tid = $jwt_arr['tid'];
$this->amr = $jwt_arr['amr'];
$this->oid = $jwt_arr['oid'];
$this->upn = $jwt_arr['upn'];
$this->puid = $jwt_arr['puid'];
$this->sub = $jwt_arr['sub'];
$this->given_name = $jwt_arr['given_name'];
$this->family_name = $jwt_arr['family_name'];
$this->name = $jwt_arr['name'];
$this->unique_name = $jwt_arr['unique_name'];
$this->appid = $jwt_arr['appid'];
$this->appidacr = $jwt_arr['appidacr'];
$this->scp = $jwt_arr['scp'];
$this->acr = $jwt_arr['acr'];
}
/**
* @return mixed
*/
public function getAud()
{
return $this->aud;
}
/**
* @param mixed $aud
*/
public function setAud($aud)
{
$this->aud = $aud;
}
/**
* @return mixed
*/
public function getIss()
{
return $this->iss;
}
/**
* @param mixed $iss
*/
public function setIss($iss)
{
$this->iss = $iss;
}
/**
* @return mixed
*/
public function getIat()
{
return $this->iat;
}
/**
* @param mixed $iat
*/
public function setIat($iat)
{
$this->iat = $iat;
}
/**
* @return mixed
*/
public function getNbf()
{
return $this->nbf;
}
/**
* @param mixed $nbf
*/
public function setNbf($nbf)
{
$this->nbf = $nbf;
}
/**
* @return mixed
*/
public function getExp()
{
return $this->exp;
}
/**
* @param mixed $exp
*/
public function setExp($exp)
{
$this->exp = $exp;
}
/**
* @return mixed
*/
public function getVer()
{
return $this->ver;
}
/**
* @param mixed $ver
*/
public function setVer($ver)
{
$this->ver = $ver;
}
/**
* @return mixed
*/
public function getTid()
{
return $this->tid;
}
/**
* @param mixed $tid
*/
public function setTid($tid)
{
$this->tid = $tid;
}
/**
* @return mixed
*/
public function getAmr()
{
return $this->amr;
}
/**
* @param mixed $amr
*/
public function setAmr($amr)
{
$this->amr = $amr;
}
/**
* @return mixed
*/
public function getOid()
{
return $this->oid;
}
/**
* @param mixed $oid
*/
public function setOid($oid)
{
$this->oid = $oid;
}
/**
* @return mixed
*/
public function getUpn()
{
return $this->upn;
}
/**
* @param mixed $upn
*/
public function setUpn($upn)
{
$this->upn = $upn;
}
/**
* @return mixed
*/
public function getPuid()
{
return $this->puid;
}
/**
* @param mixed $puid
*/
public function setPuid($puid)
{
$this->puid = $puid;
}
/**
* @return mixed
*/
public function getSub()
{
return $this->sub;
}
/**
* @param mixed $sub
*/
public function setSub($sub)
{
$this->sub = $sub;
}
/**
* @return mixed
*/
public function getGivenName()
{
return $this->given_name;
}
/**
* @param mixed $given_name
*/
public function setGivenName($given_name)
{
$this->given_name = $given_name;
}
/**
* @return mixed
*/
public function getFamilyName()
{
return $this->family_name;
}
/**
* @param mixed $family_name
*/
public function setFamilyName($family_name)
{
$this->family_name = $family_name;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return mixed
*/
public function getUniqueName()
{
return $this->unique_name;
}
/**
* @param mixed $unique_name
*/
public function setUniqueName($unique_name)
{
$this->unique_name = $unique_name;
}
/**
* @return mixed
*/
public function getAppid()
{
return $this->appid;
}
/**
* @param mixed $appid
*/
public function setAppid($appid)
{
$this->appid = $appid;
}
/**
* @return mixed
*/
public function getAppidacr()
{
return $this->appidacr;
}
/**
* @param mixed $appidacr
*/
public function setAppidacr($appidacr)
{
$this->appidacr = $appidacr;
}
/**
* @return mixed
*/
public function getScp()
{
return $this->scp;
}
/**
* @param mixed $scp
*/
public function setScp($scp)
{
$this->scp = $scp;
}
/**
* @return mixed
*/
public function getAcr()
{
return $this->acr;
}
/**
* @param mixed $acr
*/
public function setAcr($acr)
{
$this->acr = $acr;
}
public function toString(){
return "JWT ==> <br/>
aud: ".$this->aud."<br/>
iss: ". $this->iss ."<br/>
iat: ". $this->iat ."<br/>
nbf: ". $this->nbf ."<br/>
exp: ". $this->exp ."<br/>
ver: ". $this->ver ."<br/>
tid: ". $this->tid ."<br/>
amr pwd: ". $this->amr->pwd ."<br/>
oid: ". $this->oid ."<br/>
upn: ". $this->upn ."<br/>
puid: ". $this->puid ."<br/>
sub: ". $this->sub ."<br/>
given_name: ". $this->given_name ."<br/>
family_name: ". $this->family_name ."<br/>
name: ". $this->name ."<br/>
unique_name: ". $this->unique_name ."<br/>
appid: ". $this->appid ."<br/>
appidacr: ". $this->appidacr ."<br/>
scp: ". $this->scp ."<br/>
acr: ". $this->acr;
}
}
以下是JWT阵列的真实外观
/********
* Another Example JWT from microsoft site https://msdn.microsoft.com/library/office/dn707383.aspx
*
* {
"aud": "https://manage.office.com",
"iss": "https://sts.windows.net/41463f53-8812-40f4-890f-865bf6e35190/",
"iat": 1427246416,
"nbf": 1427246416,
"exp": 1427250316,
"ver": "1.0",
"tid": "41463f53-8812-40f4-890f-865bf6e35190",
"amr": [
"pwd"
],
"oid": "1cef1fdb-ff52-48c4-8e4e-dfb5ea83d357",
"upn": "admin@contoso.onmicrosoft.com",
"puid": "1003BFFD8EC47CA6",
"sub": "7XpD5OWAXM1OWmKiVKh1FOkKXV4N3OSRol6mz1pxxhU",
"given_name": "John",
"family_name": "Doe",
"name": "Contoso, Inc.",
"unique_name": "admin@contoso.onmicrosoft.com",
"appid": "a6099727-6b7b-482c-b509-1df309acc563",
"appidacr": "1",
"scp": "ActivityFeed.Read ServiceHealth.Read",
"acr": "1"
}
*
*
*/
HttpPost.php
<?php
/**
* Created by PhpStorm.
* User: msen
* Date: 3/10/16
* Time: 12:13 PM
*/
class HttpPost
{
public $url;
public $postString;
public $httpResponse;
public $ch;
public function __construct($url) {
$this->url = $url;
$this->ch = curl_init ( $this->url );
curl_setopt ( $this->ch, CURLOPT_FOLLOWLOCATION, false );
curl_setopt ( $this->ch, CURLOPT_HEADER, false );
curl_setopt ( $this->ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $this->ch, CURLOPT_SSL_VERIFYPEER, false );
}
public function __destruct() {
curl_close ( $this->ch );
}
public function setPostData($params) {
// http_build_query encodes URLs, which breaks POST data
$this->postString = rawurldecode ( http_build_query ( $params ) );
curl_setopt ( $this->ch, CURLOPT_POST, true );
curl_setopt ( $this->ch, CURLOPT_POSTFIELDS, $this->postString );
}
public function send() {
$this->httpResponse = curl_exec ( $this->ch );
}
public function getHttpResponse() {
return $this->httpResponse;
}
}
Office365_Client.php
<?php
/**
* Created by PhpStorm.
* User: msen
* Date: 3/10/16
* Time: 11:58 AM
*/
require_once "config.php";
require_once "JWT.php";
require_once "HttpPost.php";
class Office365_Client
{
private $code;
private $accessToken;
private $refreshToken;
private $id_token;
private $jwt;
public function __construct($config = array()) {
global $apiConfig;
$apiConfig = array_merge ( $apiConfig, $config );
}
public function createAuthUrl() {
global $apiConfig;
$query_params = array ('response_type' => 'code','client_id' => $apiConfig ['oauth2_client_id'],'client_secret' => $apiConfig ['oauth2_secret'],'redirect_uri' => $apiConfig ['oauth2_redirect'],'resource' => $apiConfig ['resource'],'state' => $apiConfig ['state']
);
$auth_url = $apiConfig ['oauth2_auth_url'] . '?' . http_build_query ( $query_params );
return $auth_url;
}
public function fetchTokens() {
global $apiConfig;
$url = $apiConfig['oauth2_token_url'];
$params = array ("code" => $this->code,"client_id" => $apiConfig ['oauth2_client_id'],"client_secret" =>$apiConfig ['oauth2_secret'],"resource" => $apiConfig ['resource'],"redirect_uri" => $apiConfig ['oauth2_redirect'],"grant_type" => "authorization_code"
);
// build a new HTTP POST request
$request = new HttpPost ( $url );
$request->setPostData ( $params );
$request->send();
$responseObj = json_decode($request->getHttpResponse ());
$this->accessToken = $responseObj->access_token;
$this->refreshToken = $responseObj->refresh_token;
$this->id_token = $responseObj->id_token;
}
// Fetches JWT returned from Azure to get the user's info
public function fetchJWT() {
$token_parts = explode(".", $this->getIdToken());
// First part is header, which we ignore
// Second part is JWT, which we want to parse
// First, in case it is url-encoded, fix the characters to be
// valid base64
$encoded_token = str_replace('-', '+', $token_parts[1]);
$encoded_token = str_replace('_', '/', $encoded_token);
// Next, add padding if it is needed.
switch (strlen($encoded_token) % 4){
case 0:
// No pad characters needed.
break;
case 2:
$encoded_token = $encoded_token."==";
error_log("Added 2: ".$encoded_token);
break;
case 3:
$encoded_token = $encoded_token."=";
error_log("Added 1: ".$encoded_token);
break;
default:
// Invalid base64 string!
return null;
}
$json_string = base64_decode($encoded_token);
$jwt_arr = json_decode($json_string, true);
$this->jwt = new JWT($jwt_arr);
}
/**
* @return mixed
*/
public function getCode()
{
return $this->code;
}
/**
* @param mixed $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* @return mixed
*/
public function getAccessToken()
{
return $this->accessToken;
}
/**
* @param mixed $accessToken
*/
public function setAccessToken($accessToken)
{
$this->accessToken = $accessToken;
}
/**
* @return mixed
*/
public function getRefreshToken()
{
return $this->refreshToken;
}
/**
* @param mixed $refreshToken
*/
public function setRefreshToken($refreshToken)
{
$this->refreshToken = $refreshToken;
}
/**
* @return mixed
*/
public function getIdToken()
{
return $this->id_token;
}
/**
* @param mixed $id_token
*/
public function setIdToken($id_token)
{
$this->id_token = $id_token;
}
/**
* @return JWT
*/
public function getJwt()
{
return $this->jwt;
}
/**
* @param JWT $jwt
*/
public function setJwt($jwt)
{
$this->jwt = $jwt;
}
public function toString(){
return "Office365 ==> <br/>
code: ". $this->code ."<br/>".
"accessToken: ". $this->accessToken ."<br/>".
"refreshToken: ".$this->refreshToken ."<br/>";
}
}
这是您与Office 365交互的文件
oauth2.php
<?php
/**
* Created by PhpStorm.
* User: msen
* Date: 3/10/16
* Time: 12:25 PM
*/
require_once('Office365_Client.php');
session_start();
$client = new Office365_Client();
$forward_url = $client->createAuthUrl();
if(isset($_GET['code'])) {
//TODO: verfiy unquie key state to check CSRF attack
$code = $_GET['code'];
$client->setCode($code);
//get tokens
$client->fetchTokens();
echo '<br/><br/>';
//print access tokens
print($client->toString());
echo '<br/><br/>';
//you can set the tokens into your own session
$_SESSION['accesstoken'] = $client->getAccessToken();
$_SESSION['refreshtoken'] = $client->getRefreshToken();
//let's get user info
$client->fetchJWT();
//print the usr info
print($client->getJwt()->toString());
//put the user token info into sessions
$_SESSION['name'] = $client->getJwt()->getName();//full name of the user
$_SESSION['unique_name'] = $client->getJwt()->getUniqueName();//could be email or id from office365
$_SESSION['tid'] = $client->getJwt()->getTid();//tenant id
} else{
//instead of putting a button, you can forward automatically yourself
print "<a class='login' href='$forward_url'>Connect Me!</a>";
//you can also redirect automatically
//header( 'Location: '.$forward_url );
}
?>