Last active
May 8, 2019 06:36
-
-
Save bekco/c14252d616b3bc17d5d2dd64fd543669 to your computer and use it in GitHub Desktop.
How to Authenticate (Facebook, Google +, Twitter etc.) users with HWIOauthBundle and FOSOauthServerBundle from iOS, Android or third party application using API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* User: bekco (Behçet Mutlu) | |
* Date: 17/11/16 | |
* Time: 17:52 | |
*/ | |
namespace Acme\Oauth2Bundle\Oauth\Extension; | |
use Facebook\Exceptions\FacebookAuthenticationException; | |
use Facebook\Exceptions\FacebookAuthorizationException; | |
use FOS\OAuthServerBundle\Storage\GrantExtensionInterface; | |
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwnerInterface; | |
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface; | |
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken; | |
use HWI\Bundle\OAuthBundle\Security\Core\Exception\OAuthAwareExceptionInterface; | |
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface; | |
use OAuth2\Model\IOAuth2Client; | |
use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; | |
use Symfony\Component\Security\Core\User\UserInterface; | |
class ResourceOwnerGrantExtension implements GrantExtensionInterface | |
{ | |
protected $userProvider = null; | |
protected $resourceOwner = null; | |
public function __construct(OAuthAwareUserProviderInterface $userProvider, ResourceOwnerInterface $resourceOwner) | |
{ | |
$this->userProvider = $userProvider; | |
$this->resourceOwner = $resourceOwner; | |
} | |
/** | |
* Check any extended grant types. | |
* | |
* @param IOAuth2Client $client | |
* @param array $inputData Unfiltered input data. The source is *not* guaranteed to be POST (but is likely to be). | |
* @param array $authHeaders Authorization headers | |
* @return array|bool Returns false if the authorization is rejected or not support. Returns true or an associative array if you | |
* want to verify the scope: | |
* @throws \Exception | |
* @code | |
* return array( | |
* 'scope' => <stored scope values (space-separated string)>, | |
* ); | |
* @endcode | |
* | |
* @see \OAuth2\IOAuth2GrantExtension::checkGrantExtension | |
*/ | |
public function checkGrantExtension(IOAuth2Client $client, array $inputData, array $authHeaders) | |
{ | |
if (!isset($inputData['access_token'])) { | |
return false; | |
} | |
$token = new OAuthToken($inputData); | |
try { | |
// Try to get the user with the token from Open Graph | |
/** | |
* @var $userResponse UserResponseInterface | |
*/ | |
$userResponse = $this->resourceOwner->getUserInformation([ | |
'access_token' => $token->getAccessToken() | |
]); | |
try { | |
// Check if a user match in database with the resource owner id | |
$user = $this->userProvider->loadUserByOAuthUserResponse($userResponse); | |
} catch (OAuthAwareExceptionInterface $e) { | |
$e->setToken($token); | |
$e->setResourceOwnerName($token->getResourceOwnerName()); | |
throw $e; | |
} | |
if (!$user instanceof UserInterface) { | |
throw new AuthenticationServiceException('loadUserByOAuthUserResponse() must return a UserInterface.'); | |
} | |
// Else, return the access_token for the user | |
else { | |
return array( | |
'data' => $user | |
); | |
} | |
} | |
catch(FacebookAuthorizationException $e) { | |
return false; | |
} catch(FacebookAuthenticationException $e) { | |
return false; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
oauth.facebook_extension: | |
class: Acme\Oauth2Bundle\Oauth\Extension\ResourceOwnerGrantExtension | |
arguments: | |
userProvider: "@acme_fosub_user_provider" | |
respourceOwner: "@hwi_oauth.resource_owner.facebook" | |
tags: | |
- { name: fos_oauth_server.grant_extension, uri: 'https://acme.com/facebook' } | |
oauth.google_extension: | |
class: Acme\Oauth2Bundle\Oauth\Extension\ResourceOwnerGrantExtension | |
arguments: | |
userProvider: "@acme_fosub_user_provider" | |
respourceOwner: "@hwi_oauth.resource_owner.google" | |
tags: | |
- { name: fos_oauth_server.grant_extension, uri: 'https://acme.com/google' } | |
oauth.twitter_extension: | |
class: Acme\Oauth2Bundle\Oauth\Extension\ResourceOwnerGrantExtension | |
arguments: | |
userProvider: "@acme_fosub_user_provider" | |
respourceOwner: "@hwi_oauth.resource_owner.twitter" | |
tags: | |
- { name: fos_oauth_server.grant_extension, uri: 'https://acme.com/twitter' } |
@ndusan passing the client secret from the app does sound indeed like a bad approach. Did you find any alternative approach?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@bekco
Are you saying that you're doing calls within JavaScript of your SPA where you hardcode client_id and client_secret?
E.g.
My main concern is that in step 4 (if that's how you do request) in JavaScript (which is on the client side) you would have to hardcode client_id and client_secret and that's no go! Is that what you're doing in step 4 or I got that part wrong?
In general, I'm mainly interested how do you make a call to API from SPA where you have to pass client_id and client_secret and avoid allowing yourself to be hacked. It would be great if you could give me your input on this one.