Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+62 -15
View File
@@ -7,8 +7,7 @@
* @package Invision Community
* @since 29 Apr 2017
*/
define('REPORT_EXCEPTIONS', TRUE);
\define('REPORT_EXCEPTIONS', TRUE);
require '../../init.php';
class oAuthServerTokenRequest
@@ -87,7 +86,7 @@ class oAuthServerTokenRequest
*/
public function grantType( $grantType )
{
if ( !in_array( $grantType, array( 'authorization_code', 'implicit', 'client_credentials', 'password', 'refresh_token' ) ) )
if ( !\in_array( $grantType, array( 'authorization_code', 'implicit', 'client_credentials', 'password', 'refresh_token' ) ) )
{
throw new \IPS\Login\Handler\OAuth2\Exception( 'unsupported_grant_type' );
}
@@ -99,7 +98,7 @@ class oAuthServerTokenRequest
throw new \IPS\Login\Handler\OAuth2\Exception( 'unsupported_grant_type' );
}
}
elseif ( !in_array( $grantType, explode( ',', $this->client->grant_types ) ) )
elseif ( !\in_array( $grantType, explode( ',', $this->client->grant_types ) ) )
{
throw new \IPS\Login\Handler\OAuth2\Exception( 'unauthorized_client' );
}
@@ -111,10 +110,12 @@ class oAuthServerTokenRequest
/**
* Validate Authorization Code
*
* @param string $authorizationCode The Authorization Code
* @param string $authorizationCode The Authorization Code
* @param string|NULL $redirectUri The redirect URI, if provided
* @param string|NULL $codeVerifier The code verifier, if provided
* @return array|NULL
*/
public function validateAuthorizationCode( $authorizationCode, $redirectUri = NULL )
public function validateAuthorizationCode( $authorizationCode, $redirectUri = NULL, $codeVerifier = NULL )
{
try
{
@@ -140,11 +141,45 @@ class oAuthServerTokenRequest
return;
}
/* If it has a code verifier, validate that */
if ( $authorizationCode['code_challenge'] or $this->client->pkce !== 'none' )
{
if ( !$codeVerifier or !$authorizationCode['code_challenge'] )
{
return;
}
if ( $authorizationCode['code_challenge_method'] === 'S256' or $this->client->pkce === 'S256' )
{
$codeVerifier = rtrim( strtr( base64_encode( pack( 'H*', hash( 'sha256', $codeVerifier ) ) ), '+/', '-_' ), '=' );
}
if ( !\IPS\Login::compareHashes( $authorizationCode['code_challenge'], $codeVerifier ) )
{
return;
}
}
/* Check we're not banned and not validating */
$member = \IPS\Member::load( $authorizationCode['member_id'] );
if ( $member->isBanned() or $member->members_bitoptions['validating'] )
{
return;
}
/* Mark it used */
\IPS\Db::i()->update( 'core_oauth_server_authorization_codes', array( 'used' => 1 ), array( 'client_id=? AND code=?', $authorizationCode['client_id'], $authorizationCode['code'] ) );
/* Return access token */
return $this->client->generateAccessToken( \IPS\Member::load( $authorizationCode['member_id'] ), $authorizationCode['scope'] ? json_decode( $authorizationCode['scope'] ) : NULL, 'authorization_code', FALSE, $authorizationCode['code'] );
try
{
$device = $authorizationCode['device_key'] ? \IPS\Member\Device::load( $authorizationCode['device_key'] ) : NULL;
}
catch ( \UnderflowException $e )
{
$device = NULL;
}
return $this->client->generateAccessToken( $member, $authorizationCode['scope'] ? json_decode( $authorizationCode['scope'] ) : NULL, 'authorization_code', FALSE, $authorizationCode['code'], $authorizationCode['user_agent'], isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : NULL, $device );
}
catch ( \UnderflowException $e )
{
@@ -156,7 +191,7 @@ class oAuthServerTokenRequest
* Validate Password
*
* @param string $username Username
* @param string $password Password
* @param object $password The plaintext password provided by the user, wrapped in an object that can be cast to a string so it doesn't show in any logs
* @param array|null $scope Scopes
* @return array|NULL
*/
@@ -175,7 +210,10 @@ class oAuthServerTokenRequest
$member = $method->authenticateUsernamePassword( $login, $username, $password );
\IPS\Login::checkIfAccountIsLocked( $member, TRUE );
$accessToken = $this->client->generateAccessToken( $member, $scope, 'password' );
if ( !$member->isBanned() and !$member->members_bitoptions['validating'] )
{
$accessToken = $this->client->generateAccessToken( $member, $scope, 'password', FALSE, NULL, isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : NULL, isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : NULL, NULL );
}
break;
}
catch ( \IPS\Login\Exception $e )
@@ -192,7 +230,7 @@ class oAuthServerTokenRequest
{
if ( !$member or $failedMember->member_id != $failedMember->member_id )
{
$failedLogins = is_array( $failedMember->failed_logins ) ? $failedMember->failed_logins : array();
$failedLogins = \is_array( $failedMember->failed_logins ) ? $failedMember->failed_logins : array();
$failedLogins[ \IPS\Request::i()->ipAddress() ][] = time();
$failedMember->failed_logins = $failedLogins;
$failedMember->save();
@@ -212,7 +250,7 @@ class oAuthServerTokenRequest
{
if ( $this->client->client_secret )
{
return $this->client->generateAccessToken( NULL, $scope, 'client_credentials', TRUE );
return $this->client->generateAccessToken( NULL, $scope, 'client_credentials', TRUE, NULL, NULL, isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : NULL );
}
}
@@ -232,7 +270,7 @@ class oAuthServerTokenRequest
if ( $accessToken['member_id'] )
{
$member = \IPS\Member::load( $accessToken['member_id'] );
if ( !$member->member_id )
if ( !$member->member_id or $member->isBanned() or $member->members_bitoptions['validating'] )
{
return;
}
@@ -241,7 +279,16 @@ class oAuthServerTokenRequest
$originalScope = $accessToken['scope'] ? json_decode( $accessToken['scope'], TRUE ) : array();
$scope = $newScope ? array_intersect( $originalScope, $newScope ) : $originalScope;
return $this->client->generateAccessToken( $member, $scope, 'refresh_token', TRUE );
try
{
$device = $accessToken['device_key'] ? \IPS\Member\Device::load( $accessToken['device_key'] ) : NULL;
}
catch ( \UnderflowException $e )
{
$device = NULL;
}
return $this->client->generateAccessToken( $member, $scope, 'refresh_token', TRUE, NULL, $accessToken['auth_user_agent'], isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : NULL, $device, $accessToken );
}
}
}
@@ -305,10 +352,10 @@ try
switch ( $request->grantType( \IPS\Request::i()->grant_type ) )
{
case 'authorization_code':
$accessToken = $request->validateAuthorizationCode( \IPS\Request::i()->code, \IPS\Request::i()->redirect_uri );
$accessToken = $request->validateAuthorizationCode( \IPS\Request::i()->code, \IPS\Request::i()->redirect_uri, isset( \IPS\Request::i()->code_verifier ) ? \IPS\Request::i()->code_verifier : NULL );
break;
case 'password':
$accessToken = $request->validatePassword( \IPS\Request::i()->username, \IPS\Request::i()->password, isset( \IPS\Request::i()->scope ) ? explode( ' ', \IPS\Request::i()->scope ) : NULL );
$accessToken = $request->validatePassword( \IPS\Request::i()->username, \IPS\Request::i()->protect('password'), isset( \IPS\Request::i()->scope ) ? explode( ' ', \IPS\Request::i()->scope ) : NULL );
break;
case 'client_credentials':
$accessToken = $request->validateClientCredentials( isset( \IPS\Request::i()->scope ) ? explode( ' ', \IPS\Request::i()->scope ) : NULL );