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' } |
@bekco
Are you saying that you're doing calls within JavaScript of your SPA where you hardcode client_id and client_secret?
E.g.
- User requested to get signed up/signed in via Facebook (code example: https://developers.facebook.com/docs/facebook-login/web/)
- User entered Facebook credentials once asked
- Facebook did authResponse and provided
{
status: 'connected',
authResponse: {
accessToken: '...',
expiresIn:'...',
reauthorize_required_in:'...'
signedRequest:'...',
userID:'...'
}
}
- SPA will make request to API passing Facebook accessToken together with client_id and client_secret
- Your solution would then talk again to Facebook and got the user for provided Facebook accessToken and return back to SPA Bearer accessToken
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.
@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
Guys, I'm new to Symfony and PHP.
Where can I add the ResourceOwnerGrantExtension.php file?
And where is the namespace "Acme\Oauth2Bundle\Oauth\Extension" ? is it included in another bundle?
Also what are the end points that I'll call from the mobile app to comlete email registration or Google/Facebook Registration?