Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F93399725
PhutilAuthAdapterOAuth.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Thu, Nov 28, 11:48
Size
5 KB
Mime Type
text/x-php
Expires
Sat, Nov 30, 11:48 (1 d, 21 h)
Engine
blob
Format
Raw Data
Handle
22628314
Attached To
rPHU libphutil
PhutilAuthAdapterOAuth.php
View Options
<?php
/**
* Abstract adapter for OAuth2 providers.
*/
abstract
class
PhutilAuthAdapterOAuth
extends
PhutilAuthAdapter
{
private
$clientID
;
private
$clientSecret
;
private
$redirectURI
;
private
$scope
;
private
$state
;
private
$code
;
private
$accessTokenData
;
private
$oauthAccountData
;
abstract
protected
function
getAuthenticateBaseURI
();
abstract
protected
function
getTokenBaseURI
();
abstract
protected
function
loadOAuthAccountData
();
public
function
getAuthenticateURI
()
{
$uri
=
new
PhutilURI
(
$this
->
getAuthenticateBaseURI
());
$uri
->
setQueryParam
(
'client_id'
,
$this
->
getClientID
());
$uri
->
setQueryParam
(
'scope'
,
$this
->
getScope
());
$uri
->
setQueryParam
(
'redirect_uri'
,
$this
->
getRedirectURI
());
$uri
->
setQueryParam
(
'state'
,
$this
->
getState
());
foreach
(
$this
->
getExtraAuthenticateParameters
()
as
$key
=>
$value
)
{
$uri
->
setQueryParam
(
$key
,
$value
);
}
return
(
string
)
$uri
;
}
public
function
getAdapterType
()
{
$this_class
=
get_class
(
$this
);
$type_name
=
str_replace
(
'PhutilAuthAdapterOAuth'
,
''
,
$this_class
);
return
strtolower
(
$type_name
);
}
public
function
setState
(
$state
)
{
$this
->
state
=
$state
;
return
$this
;
}
public
function
getState
()
{
return
$this
->
state
;
}
public
function
setCode
(
$code
)
{
$this
->
code
=
$code
;
return
$this
;
}
public
function
getCode
()
{
return
$this
->
code
;
}
public
function
setRedirectURI
(
$redirect_uri
)
{
$this
->
redirectURI
=
$redirect_uri
;
return
$this
;
}
public
function
getRedirectURI
()
{
return
$this
->
redirectURI
;
}
public
function
getExtraAuthenticateParameters
()
{
return
array
();
}
public
function
getExtraTokenParameters
()
{
return
array
();
}
public
function
getExtraRefreshParameters
()
{
return
array
();
}
public
function
setScope
(
$scope
)
{
$this
->
scope
=
$scope
;
return
$this
;
}
public
function
getScope
()
{
return
$this
->
scope
;
}
public
function
setClientSecret
(
PhutilOpaqueEnvelope
$client_secret
)
{
$this
->
clientSecret
=
$client_secret
;
return
$this
;
}
public
function
getClientSecret
()
{
return
$this
->
clientSecret
;
}
public
function
setClientID
(
$client_id
)
{
$this
->
clientID
=
$client_id
;
return
$this
;
}
public
function
getClientID
()
{
return
$this
->
clientID
;
}
public
function
getAccessToken
()
{
return
$this
->
getAccessTokenData
(
'access_token'
);
}
public
function
getAccessTokenExpires
()
{
return
$this
->
getAccessTokenData
(
'expires_epoch'
);
}
public
function
getRefreshToken
()
{
return
$this
->
getAccessTokenData
(
'refresh_token'
);
}
protected
function
getAccessTokenData
(
$key
,
$default
=
null
)
{
if
(
$this
->
accessTokenData
===
null
)
{
$this
->
accessTokenData
=
$this
->
loadAccessTokenData
();
}
return
idx
(
$this
->
accessTokenData
,
$key
,
$default
);
}
public
function
supportsTokenRefresh
()
{
return
false
;
}
public
function
refreshAccessToken
(
$refresh_token
)
{
$this
->
accessTokenData
=
$this
->
loadRefreshTokenData
(
$refresh_token
);
return
$this
;
}
protected
function
loadRefreshTokenData
(
$refresh_token
)
{
$params
=
array
(
'refresh_token'
=>
$refresh_token
,
)
+
$this
->
getExtraRefreshParameters
();
// NOTE: Make sure we return the refresh_token so that subsequent
// calls to getRefreshToken() return it; providers normally do not echo
// it back for token refresh requests.
return
$this
->
makeTokenRequest
(
$params
)
+
array
(
'refresh_token'
=>
$refresh_token
,
);
}
protected
function
loadAccessTokenData
()
{
$code
=
$this
->
getCode
();
if
(!
$code
)
{
throw
new
Exception
(
'Call setCode() before accessing adapter information.'
);
}
$params
=
array
(
'code'
=>
$this
->
getCode
(),
)
+
$this
->
getExtraTokenParameters
();
return
$this
->
makeTokenRequest
(
$params
);
}
private
function
makeTokenRequest
(
array
$params
)
{
$uri
=
$this
->
getTokenBaseURI
();
$query_data
=
array
(
'client_id'
=>
$this
->
getClientID
(),
'client_secret'
=>
$this
->
getClientSecret
()->
openEnvelope
(),
'redirect_uri'
=>
$this
->
getRedirectURI
(),
)
+
$params
;
$future
=
new
HTTPSFuture
(
$uri
,
$query_data
);
$future
->
setMethod
(
'POST'
);
list
(
$body
)
=
$future
->
resolvex
();
$data
=
$this
->
readAccessTokenResponse
(
$body
);
if
(
isset
(
$data
[
'expires_in'
]))
{
$data
[
'expires_epoch'
]
=
$data
[
'expires_in'
];
}
else
if
(
isset
(
$data
[
'expires'
]))
{
$data
[
'expires_epoch'
]
=
$data
[
'expires'
];
}
// If we got some "expires" value back, interpret it as an epoch timestamp
// if it's after the year 2010 and as a relative number of seconds
// otherwise.
if
(
isset
(
$data
[
'expires_epoch'
]))
{
if
(
$data
[
'expires_epoch'
]
<
(
60
*
60
*
24
*
365
*
40
))
{
$data
[
'expires_epoch'
]
+=
time
();
}
}
if
(
isset
(
$data
[
'error'
]))
{
throw
new
Exception
(
'Access token error: '
.
$data
[
'error'
]);
}
return
$data
;
}
protected
function
readAccessTokenResponse
(
$body
)
{
// NOTE: Most providers either return JSON or HTTP query strings, so try
// both mechanisms. If your provider does something else, override this
// method.
$data
=
json_decode
(
$body
,
true
);
if
(!
is_array
(
$data
))
{
$data
=
array
();
parse_str
(
$body
,
$data
);
}
if
(
empty
(
$data
[
'access_token'
])
&&
empty
(
$data
[
'error'
]))
{
throw
new
Exception
(
"Failed to decode OAuth access token response: {$body}"
);
}
return
$data
;
}
protected
function
getOAuthAccountData
(
$key
,
$default
=
null
)
{
if
(
$this
->
oauthAccountData
===
null
)
{
$this
->
oauthAccountData
=
$this
->
loadOAuthAccountData
();
}
return
idx
(
$this
->
oauthAccountData
,
$key
,
$default
);
}
}
Event Timeline
Log In to Comment