-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Basic implementation of Google OAuth via authorization code #54
Basic implementation of Google OAuth via authorization code #54
Conversation
Great addition, I started refactoring the authentication earlier today. What do you think of this approach? /~https://github.com/NicklasWallgren/PokemonGoAPI-PHP/commits/authentication-managers |
I understand this right, it means we can store the auth token ourselves, and "relogin" with them without re-logging in on every page refresh/CLI call? My use case/wish list for the login process:
(Maybe we should move this discussion to an issue XD) |
@Ni42 : I had it implemented like that in my personal project/playground: interface AuthInterface
{
/**
* The auth mechanism the implementation represents.
*
* @return string
*/
public function getAuthType():string;
/**
* Get the identifier for the account this tries to login to (most likely a username).
*
* @return string
*/
public function getUniqueIdentifier():string;
/**
* Use this AuthInterface to get an access token.
*
* @return AccessToken
*
* @throws AuthException
*/
public function invoke(): AccessToken;
} /**
* Perform the login.
*
* @return PlayerData
*/
public function login():PlayerData
{
/** @var AuthInterface $auth */
$auth = null;
try {
$auth = $this->container->get(AuthInterface::class);
} catch (AliasNotFound $e) {
throw new \BadMethodCallException('You need to set an auth mechanism with setAuth', 0, $e);
}
$cacheKey = [$auth->getAuthType(), $auth->getUniqueIdentifier()];
$item = $this->cache->getItem(static::cacheKey($cacheKey));
if ($item->isHit()) {
$this->logger->debug('Login Cache hit');
$this->accessToken = $item->get();
} else {
$this->logger->info('Cache miss -> Doing login');
$accessToken = $auth->invoke();
$this->accessToken = $accessToken->getToken();
$lifetime = $accessToken->getLifetime();
$item->set($this->accessToken);
if ($lifetime instanceof \DateTimeInterface) {
$item->expiresAt($lifetime);
} else {
$item->expiresAfter($lifetime);
}
$this->cache->save($item);
}
(...)
$this->logger->notice('Using AccessToken '.$this->accessToken);
$playerData = $this->initialize();
$this->logger->notice('Login completed. Logged in as '.$playerData->getUsername());
return $playerData;
} class AccessToken
{
/** @var string */
protected $token;
/** @var int */
protected $lifetime;
/**
* AccessToken constructor.
*
* @param string $token
* @param int|\DateTimeInterface|\DateInterval $lifetime
*/
public function __construct(string $token, $lifetime)
{
if (!(is_int($lifetime) || $lifetime instanceof \DateTimeInterface || $lifetime instanceof \DateInterval)) {
throw new \BadMethodCallException('Lifetime must be an integer or instance of DateTimeInterface / DateInterval');
}
$this->token = $token;
$this->lifetime = $lifetime;
}
/**
* Get the access token.
*
* @return string
*/
public function getToken():string
{
return $this->token;
}
/**
* Get the lifetime.
*
* @return int|\DateTimeInterface|\DateInterval
*/
public function getLifetime()
{
return $this->lifetime;
}
} By forcing |
Yep, looked through your things a little while ago, I liked that part:+1: |
@NicklasWallgren : Your new concept of the Authentication looks good to me. |
Here is my latest addition.
|
Very clean solution in my opinion, I think better then passing a cache into the application 👍 . How would one implement something like on pokeadvisor ❓ : User provides authorization code -> application exchanges it for access and refresh token. Wouldn't I need 3 managers but can only pass one? Edit: Because I want to save the exchanged tokens in something (session) and use them again, even though the end-user only provides auth codes. |
I guess this would work, or am I missing something?
|
No, this is good, thank you for clearing it up. I was thinking in a more CLI'ish context where I only have on entry point, what doesn't have to be like this of course. Now that I see your example it makes perfect sense. Closing this since it wouldn't be compatible with how you are refactoring the auth-system. and also implemented it yourself. |
Thanks for the input / contribution @DrDelay. Much appreciated :) |
Regarding #39 and #52 , this lets users use do:
The first parameter could in the future be used to cache the refresh_token. It is not relevant however as long as the authorization code is valid. It can be obtained here: https://accounts.google.com/o/oauth2/auth?client_id=848232511240-73ri3t7plvk96pj4f85uj8otdat2alem.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&scope=openid%20email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&approval_prompt=force