소셜 애플로그인 연동
본문
<?php
/*!
* Hybridauth
* https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
* (c) 2020 Hybridauth authors | https://hybridauth.github.io/license.html
*/
class Hybrid_Providers_Apple extends Hybrid_Provider_Model_OAuth2
{
public $scope = "name email";
public $AuthorizeUrlParametersEncType = "PHP_QUERY_RFC3986";
/**
* initialization
*/
function initialize()
{
parent::initialize();
// Provider API end-points
$this->api->api_base_url = "https://appleid.apple.com/auth/";
$this->api->authorize_url = "https://appleid.apple.com/auth/authorize";
$this->api->access_token_url = "https://appleid.apple.com/auth/token";
$this->AuthorizeUrlParameters['response_mode'] = "form_post";
if (!$this->config["keys"]["id"] || !$this->config["keys"]["secret"]) {
throw new Exception("Your application id and secret are required in order to connect to {$this->providerId}.", 4);
}
// redirect uri mismatches when authenticating with Apple.
if (isset($this->config['redirect_uri']) && !empty($this->config['redirect_uri'])) {
$this->api->redirect_uri = $this->config['redirect_uri'];
}
}
/**
* {@inheritdoc}
*/
function configure()
{
$keys = $this->config->get('keys');
$keys['secret'] = $this->getSecret();
$this->config->set('keys', $keys);
return parent::configure();
}
/**
* {@inheritdoc}
*
* include id_token $tokenNames
*/
function getAccessToken()
{
$tokenNames = [
'access_token',
'id_token',
'access_token_secret',
'token_type',
'refresh_token',
'expires_in',
'expires_at',
];
$tokens = [];
foreach ($tokenNames as $name) {
if ($this->getStoredData($name)) {
$tokens[$name] = $this->getStoredData($name);
}
}
return $tokens;
}
/**
* {@inheritdoc}
*/
function validateAccessTokenExchange($response)
{
$collection = parent::validateAccessTokenExchange($response);
$this->storeData('id_token', $collection->get('id_token'));
return $collection;
}
function getUserProfile()
{
$id_token = $this->getStoredData('id_token');
$verifyTokenSignature =
($this->config->exists('verifyTokenSignature')) ? $this->config->get('verifyTokenSignature') : true;
if (!$verifyTokenSignature) {
// payload extraction by https://github.com/omidborjian
// https://github.com/hybridauth/hybridauth/issues/1095#issuecomment-626479263
// JWT splits the string to 3 components 1) first is header 2) is payload 3) is signature
$payload = explode('.', $id_token)[1];
$payload = json_decode(base64_decode($payload));
} else {
// validate the token signature and get the payload
$publicKeys = $this->apiRequest('keys');
\Firebase\JWT\JWT::$leeway = 120;
foreach ($publicKeys->keys as $publicKey) {
try {
$rsa = new RSA();
$jwk = (array)$publicKey;
$rsa->loadKey(
[
'e' => new BigInteger(base64_decode($jwk['e']), 256),
'n' => new BigInteger(base64_decode(strtr($jwk['n'], '-_', '+/'), true), 256)
]
);
$pem = $rsa->getPublicKey();
$payload = JWT::decode($id_token, $pem, ['RS256']);
$error = false;
break;
} catch (\Exception $e) {
$error = $e->getMessage();
if ($e instanceof \Firebase\JWT\ExpiredException) {
break;
}
}
}
if ($error) {
throw new \Exception($error);
}
}
$data = new Data\Collection($payload);
if (!$data->exists('sub')) {
throw new UnexpectedValueException('Missing token payload.');
}
/*$userProfile = new User\Profile();
$userProfile->identifier = $data->get('sub');
$userProfile->email = $data->get('email');
$this->storeData('expires_at', $data->get('exp'));
if (!empty($_REQUEST['user'])) {
$objUser = json_decode($_REQUEST['user']);
$user = new Data\Collection($objUser);
if (!$user->isEmpty()) {
$name = $user->get('name');
$userProfile->firstName = $name->firstName;
$userProfile->lastName = $name->lastName;
$userProfile->displayName = join(' ', [$userProfile->firstName, $userProfile->lastName]);
}
}
return $userProfile;*/
# store the user profile.
$this->user->profile->identifier = $data->get('sub');
$this->user->profile->email = $data->get('email');
$this->storeData('expires_at', $data->get('exp'));
$this->user->profile->sid = get_social_convert_id( $this->user->profile->identifier, $this->providerId );
return $this->user->profile;
}
/**
* @return string secret token
*/
private function getSecret()
{
// Your 10-character Team ID
if (!$team_id = $this->config->filter('keys')->get('team_id')) {
throw new InvalidApplicationCredentialsException(
'Missing parameter team_id: your team id is required to generate the JWS token.'
);
}
// Your Services ID, e.g. com.aaronparecki.services
if (!$client_id = $this->config->filter('keys')->get('id') ?: $this->config->filter('keys')->get('key')) {
throw new InvalidApplicationCredentialsException(
'Missing parameter id: your client id is required to generate the JWS token.'
);
}
// Find the 10-char Key ID value from the portal
if (!$key_id = $this->config->filter('keys')->get('key_id')) {
throw new InvalidApplicationCredentialsException(
'Missing parameter key_id: your key id is required to generate the JWS token.'
);
}
// Find the 10-char Key ID value from the portal
$key_content = $this->config->filter('keys')->get('key_content');
// Save your private key from Apple in a file called `key.txt`
if (!$key_content) {
if (!$key_file = $this->config->filter('keys')->get('key_file')) {
throw new InvalidApplicationCredentialsException(
'Missing parameter key_content or key_file: your key is required to generate the JWS token.'
);
}
if (!file_exists($key_file)) {
throw new InvalidApplicationCredentialsException(
"Your key file $key_file does not exist."
);
}
$key_content = file_get_contents($key_file);
}
$data = [
'iat' => time(),
'exp' => time() + 86400 * 180,
'iss' => $team_id,
'aud' => 'https://appleid.apple.com',
'sub' => $client_id
];
$secret = JWT::encode($data, $key_content, 'ES256', $key_id);
return $secret;
}
}
https://github.com/hybridauth/hybridauth/blob/master/src/Provider/Apple.php
애플로그인 연동을 위해 위 파일을 그누보드에 맞게 initialize와 getUserProfile만 위 소스와 같이 조금 수정해줬는데 아이디 비밀번호 쓰는창이 나오고 로그인까지는 되는데 그 이 후에
"사용자 프로필 요청이 실패했습니다.사용자가 해당 서비스에 연결되어 있지 않을 경우도 있습니다. 이 경우 다시 인증 요청을 해야 합니다."
이렇게 에러가 뜨는데 혹시 어디가 잘못된걸까요? 몇주째 해결하지 못하고 있네요
혹시 그누보드에 애플로그인 연동하신분이 계시다면 도움 부탁드립니다!
/plugin/social/includes/functions.php 경로에 provider는 추가했습니다.
// Apple
$r['Apple'] = array(
"enabled" => option_array_checked('apple', $config['cf_social_servicelist']) ? true : false,
"keys" => array("id" => $config['cf_apple_clientid'], "secret" => $config['cf_apple_secret']),
"redirect_uri" => get_social_callbackurl('apple'),
"trustForwarded" => false
);
!-->!-->
답변을 작성하시기 전에 로그인 해주세요.