Version 5.0.0 beta 1

This commit is contained in:
Neo committed 2025-12-19 16:27:35 -08:00
1 parent 25ddeb65d6
commit 15c7beabc5
6736 files changed
+627902 -497943

No files matched your search

+77 -66
View File
@@ -11,23 +11,38 @@
namespace IPS\Login\Handler\OAuth2;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
use Exception;
use IPS\File;
use IPS\Helpers\Form\Text;
use IPS\Helpers\Form\Upload;
use IPS\Http\Url;
use IPS\Login;
use IPS\Login\Exception as LoginException;
use IPS\Member;
use IPS\Theme;
use function defined;
use function in_array;
use function is_array;
use function is_string;
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* Sign In With Apple Login Handler
*/
class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
class Apple extends OpenID
{
/**
* Get title
*
* @return string
*/
public static function getTitle()
public static function getTitle(): string
{
return 'login_handler_Apple';
}
@@ -37,7 +52,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
*
* @return string
*/
protected function _authenticationType()
protected function _authenticationType(): string
{
return static::AUTHENTICATE_POST;
}
@@ -50,9 +65,9 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
return array( 'savekey' => new \IPS\Helpers\Form\[Type]( ... ), ... );
* @endcode
*/
public function acpForm()
public function acpForm(): array
{
\IPS\Member::loggedIn()->language()->words['oauth_client_id'] = \IPS\Member::loggedIn()->language()->addToStack('login_apple_services_id');
Member::loggedIn()->language()->words['oauth_client_id'] = Member::loggedIn()->language()->addToStack('login_apple_services_id');
$return = array();
$return[] = array( 'login_handler_apple_settings', 'login_handler_Apple_info' );
@@ -66,16 +81,16 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
{
$active = 'accountManagementSettings';
}
if ( !\is_string( $v ) and !\is_array( $v ) and $k !== 'client_secret' )
if ( !is_string( $v ) and !is_array( $v ) and $k !== 'client_secret' )
{
${$active}[ $k ] = $v;
}
}
$return['apple_team_id'] = new \IPS\Helpers\Form\Text( 'apple_team_id', isset( $this->settings['apple_team_id'] ) ? $this->settings['apple_team_id'] : NULL, NULL, array(), NULL, NULL, NULL, 'apple_team_id' );
$return['apple_key_id'] = new \IPS\Helpers\Form\Text( 'apple_key_id', isset( $this->settings['apple_key_id'] ) ? $this->settings['apple_key_id'] : NULL, NULL, array(), NULL, NULL, NULL, 'apple_key_id' );
$return['apple_key'] = new \IPS\Helpers\Form\Upload( 'apple_key', ( isset( $this->settings['apple_key'] ) and $this->settings['apple_key'] ) ? \IPS\File::get( 'core_Login', $this->settings['apple_key'] ) : NULL, TRUE, array( 'storageExtension' => 'core_Login', 'allowedFileTypes' => ['p8'] ), NULL, NULL, NULL, 'apple_key' );;
$return['apple_team_id'] = new Text( 'apple_team_id', $this->settings['apple_team_id'] ?? NULL, NULL, array(), NULL, NULL, NULL, 'apple_team_id' );
$return['apple_key_id'] = new Text( 'apple_key_id', $this->settings['apple_key_id'] ?? NULL, NULL, array(), NULL, NULL, NULL, 'apple_key_id' );
$return['apple_key'] = new Upload( 'apple_key', ( isset( $this->settings['apple_key'] ) and $this->settings['apple_key'] ) ? File::get( 'core_Login', $this->settings['apple_key'] ) : NULL, TRUE, array( 'storageExtension' => 'core_Login', 'allowedFileTypes' => ['p8'] ), NULL, NULL, NULL, 'apple_key' );
$return[] = 'account_management_settings';
foreach ( $accountManagementSettings as $k => $v )
{
@@ -91,7 +106,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* @param array $values Values from form
* @return array
*/
public function acpFormSave( &$values )
public function acpFormSave( array &$values ): array
{
$return = parent::acpFormSave( $values );
$return['apple_key'] = (string) $return['apple_key'];
@@ -104,7 +119,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
*
* @return string
*/
public function buttonColor()
public function buttonColor(): string
{
return '#000000';
}
@@ -114,7 +129,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
*
* @return string
*/
public function buttonIcon()
public function buttonIcon(): string
{
return 'apple';
}
@@ -124,7 +139,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
*
* @return string
*/
public function buttonText()
public function buttonText(): string
{
return 'login_apple';
}
@@ -134,20 +149,20 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
*
* @return string
*/
public function buttonClass()
public function buttonClass(): string
{
return 'ipsSocial_apple';
return 'ipsSocial--apple';
}
/**
* Get logo to display in information about logins with this method
* Returns NULL for methods where it is not necessary to indicate the method, e..g Standard
*
* @return \IPS\Http\Url
* @return Url|string|null
*/
public function logoForDeviceInformation()
public function logoForDeviceInformation(): Url|string|null
{
return \IPS\Theme::i()->resource( 'logos/login/Apple.png', 'core', 'interface' );
return Theme::i()->resource( 'logos/login/Apple.png', 'core', 'interface' );
}
/**
@@ -155,7 +170,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
*
* @return string
*/
protected function grantType()
protected function grantType(): string
{
return 'authorization_code';
}
@@ -163,46 +178,42 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
/**
* Get scopes to request
*
* @param array|NULL $additional Any additional scopes to request
* @param array|null $additional Any additional scopes to request
* @return array
*/
protected function scopesToRequest( $additional=NULL )
protected function scopesToRequest( array $additional=NULL ): array
{
$return = array( 'name email' );
return $return;
return array( 'name email' );
}
/**
* Authorization Endpoint
*
* @param \IPS\Login $login The login object
* @return \IPS\Http\Url
* @param Login $login The login object
* @return Url
*/
protected function authorizationEndpoint( \IPS\Login $login )
protected function authorizationEndpoint( Login $login ): Url
{
$return = \IPS\Http\Url::external( 'https://appleid.apple.com/auth/authorize' )->setQueryString( 'response_mode', 'form_post' );
return $return;
return Url::external( 'https://appleid.apple.com/auth/authorize' )->setQueryString( 'response_mode', 'form_post' );
}
/**
* Token Endpoint
*
* @return \IPS\Http\Url
* @return Url
*/
protected function tokenEndpoint()
protected function tokenEndpoint(): Url
{
return \IPS\Http\Url::external( 'https://appleid.apple.com/auth/token' );
return Url::external( 'https://appleid.apple.com/auth/token' );
}
/**
* Get authenticated user's identifier (may not be a number)
*
* @param string $accessToken Access Token
* @return string
* @param string $accessToken Access Token
* @return string|null
*/
protected function authenticatedUserId( $accessToken )
protected function authenticatedUserId( string $accessToken ): ?string
{
$claims = $this->getClaimsfromIdToken( $this->_getIdToken( $accessToken ) );
@@ -213,10 +224,10 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* Get authenticated user's username
* May return NULL if server doesn't support this
*
* @param string $accessToken Access Token
* @param string $accessToken Access Token
* @return string|NULL
*/
protected function authenticatedUserName( $accessToken )
protected function authenticatedUserName( string $accessToken ): ?string
{
$name = NULL;
@@ -237,10 +248,10 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* Get authenticated user's email address
* May return NULL if server doesn't support this
*
* @param string $accessToken Access Token
* @param string $accessToken Access Token
* @return string|NULL
*/
protected function authenticatedEmail( $accessToken )
protected function authenticatedEmail( string $accessToken ): ?string
{
$claims = $this->getClaimsfromIdToken( $this->_getIdToken( $accessToken ) );
@@ -251,9 +262,9 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* Client Secret
*
* @return string | NULL
* @throws \IPS\Login\Exception
* @throws LoginException
*/
public function clientSecret()
public function clientSecret(): ?string
{
$key = NULL;
@@ -261,9 +272,9 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
{
try
{
$key = \IPS\File::get( 'core_Login', $this->settings['apple_key'] )->contents();
$key = File::get( 'core_Login', $this->settings['apple_key'] )->contents();
}
catch ( \Exception $e )
catch ( Exception $e )
{
return NULL;
}
@@ -295,7 +306,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
if ( !$pKey )
{
throw new \IPS\Login\Exception( 'login_apple_invalid_key', \IPS\Login\Exception::INTERNAL_ERROR );
throw new LoginException( 'login_apple_invalid_key', LoginException::INTERNAL_ERROR );
}
$payload = $this->baseURL64encode( json_encode( $header ) ) . '.' . $this->baseURL64encode( json_encode( $data ) );
@@ -304,7 +315,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
$success = openssl_sign( $payload, $signature, $pKey, OPENSSL_ALGO_SHA256 );
if ( !$success )
{
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
throw new LoginException( 'generic_error', LoginException::INTERNAL_ERROR );
}
$rawSignature = $this->fromDER( $signature, 64 );
@@ -315,16 +326,16 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
/**
* Syncing Options
*
* @param \IPS\Member $member The member we're asking for (can be used to not show certain options iof the user didn't grant those scopes)
* @param Member $member The member we're asking for (can be used to not show certain options iof the user didn't grant those scopes)
* @param bool $defaultOnly If TRUE, only returns which options should be enabled by default for a new account
* @return array
*/
public function syncOptions( \IPS\Member $member, $defaultOnly = FALSE )
public function syncOptions( Member $member, bool $defaultOnly=FALSE ): array
{
$return = array();
$scopes = $this->authorizedScopes( $member );
if ( ( !isset( $this->settings['update_email_changes'] ) or $this->settings['update_email_changes'] === 'optional' ) and ( $scopes and \in_array( 'email', $scopes ) ) )
if ( ( !isset( $this->settings['update_email_changes'] ) or $this->settings['update_email_changes'] === 'optional' ) and ( $scopes and in_array( 'email', $scopes ) ) )
{
$return[] = 'email';
}
@@ -335,10 +346,10 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
/**
* Process an ID Token
*
* @param array $iDToken ID Token
* @param string $iDToken ID Token
* @return array
*/
protected function getClaimsfromIdToken ( $iDToken )
protected function getClaimsfromIdToken ( string $iDToken ): array
{
$claims = explode( '.', $iDToken )[1];
$claims = json_decode( base64_decode( $claims ), true );
@@ -353,15 +364,15 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* @param int $partLength
*
* @return string
* @throws \IPS\Login\Exception
* @throws LoginException
*/
public static function fromDER( string $der, int $partLength )
public static function fromDER( string $der, int $partLength ): string
{
$hex = unpack( 'H*', $der )[1];
if ( '30' !== mb_substr( $hex, 0, 2, '8bit' ) )
{
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
throw new LoginException( 'generic_error', LoginException::INTERNAL_ERROR );
}
if ( '81' === mb_substr( $hex, 2, 2, '8bit' ) )
@@ -375,7 +386,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
if ( '02' !== mb_substr( $hex, 0, 2, '8bit' ) )
{
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
throw new LoginException( 'generic_error', LoginException::INTERNAL_ERROR );
}
$Rl = hexdec( mb_substr( $hex, 2, 2, '8bit' ) );
@@ -385,7 +396,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
if ( '02' !== mb_substr( $hex, 0, 2, '8bit' ) )
{
throw new \IPS\Login\Exception( 'generic_error', \IPS\Login\Exception::INTERNAL_ERROR );
throw new LoginException( 'generic_error', LoginException::INTERNAL_ERROR );
}
$Sl = hexdec( mb_substr( $hex, 2, 2, '8bit' ) );
@@ -401,7 +412,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* @param string $data
* @return string
*/
protected static function preparePositiveInteger( string $data )
protected static function preparePositiveInteger( string $data ): string
{
if ( mb_substr( $data, 0, 2, '8bit') > '7f' )
{
@@ -421,7 +432,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* @param string $data
* @return string
*/
protected static function retrievePositiveInteger( string $data )
protected static function retrievePositiveInteger( string $data ): string
{
while ( '00' === mb_substr( $data, 0, 2, '8bit' ) && mb_substr( $data, 2, 2, '8bit' ) > '7f' )
{
@@ -437,7 +448,7 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
* @param string $data
* @return string
*/
protected function baseURL64encode( $data )
protected function baseURL64encode( string $data ): string
{
$encoded = strtr( base64_encode( $data ), '+/', '-_' );
@@ -447,17 +458,17 @@ class _Apple extends \IPS\Login\Handler\OAuth2\OpenID
/**
* Delete files
*
* @return void
* @return void
*/
public function delete()
public function delete(): void
{
if ( isset( $this->settings['apple_key'] ) )
{
try
{
\IPS\File::get( 'core_Login', $this->settings['apple_key'] )->delete();
File::get( 'core_Login', $this->settings['apple_key'] )->delete();
}
catch( \Exception $e ){}
catch( Exception $e ){}
}
parent::delete();