Jump to content

New OAuth login handler access token process


The Krotek

Recommended Posts

Posted

I'm trying to update my login handlers to new format. Mostly it's OK, but a few things bother me. Particularly, how _processAccessToken() processes token and passes it to other functions.

At some point this function calls authenticatedEmail($accessToken['access_token']) function and passes access token only. But not all social networks are made the same way. For example, VKontakte returns user email, but it does it in the same array with access token. When we exchange token for code, not only user ID, access token and expiration period are returned, but email as well. The most weird part, that this email is NOT returned in user array. So the only way to get user email is on token exchange step.

And here's the problem: since only access token is passed to authenticatedEmail() function, I can't get user email. If full accessToken array was passed like this authenticatedEmail($accessToken), problem would be solved. Same to other similar functions like authenticatedUserName(), where only access token is passed, not the full array.

Potentially I could use Update Email option for VKontatke, but for now I don't know, how override the default login handler functionality to get email and process token at the same time. Rewriting the whole _processAccessToken() function seems an awful idea.

Posted
4 minutes ago, The Krotek said:

I'm trying to update my login handlers to new format. Mostly it's OK, but a few things bother me. Particularly, how _processAccessToken() processes token and passes it to other functions.

At some point this function calls authenticatedEmail($accessToken['access_token']) function and passes access token only. But not all social networks are made the same way. For example, VKontakte returns user email, but it does it in the same array with access token. When we exchange token for code, not only user ID, access token and expiration period are returned, but email as well. The most weird part, that this email is NOT returned in user array. So the only way to get user email is on token exchange step.

And here's the problem: since only access token is passed to authenticatedEmail() function, I can't get user email. If full accessToken array was passed like this authenticatedEmail($accessToken), problem would be solved. Same to other similar functions like authenticatedUserName(), where only access token is passed, not the full array.

Potentially I could use Update Email option for VKontatke, but for now I don't know, how override the default login handler functionality to get email and process token at the same time. Rewriting the whole _processAccessToken() function seems an awful idea.

VKontakte is supported out of the box, we actually used it as the 'demo' in our feature announcement. The majority of OAuth 2 providers should work with our 'Other OAuth 2' login handler.

 

Posted

Please, read my post, don't skip the description of the issue. I never said, that VK login doesn't work. I was very specific on the matter.

Once again: VK API returns email in a non-standard way - in array with access_token, NOT with user array. This makes Update Email feature useless (always NULL returned) and seamless registration impossible (user needs to enter email manually). I provided details above, on why exactly this happens.

Your current protocol is too strict. Any non-standard value will be lost.

Posted
22 minutes ago, The Krotek said:

Please, read my post, don't skip the description of the issue. I never said, that VK login doesn't work. I was very specific on the matter.

Once again: VK API returns email in a non-standard way - in array with access_token, NOT with user array. This makes Update Email feature useless (always NULL returned) and seamless registration impossible (user needs to enter email manually). I provided details above, on why exactly this happens.

Your current protocol is too strict. Any non-standard value will be lost.

I appreciate that, I was just pointing out that VK works out of the box (granted as you pointed out, without an email address. - Which is noted in the product update).

It's very rare for a platform to provide additional parameters when responding to a token exchange, our functionality was developed against the OAuth 2 specifications which doesn't really have any allowance for this. The only other times I've really seen this done is with platforms that use a JWT as the access token - Which is an idea I quite like, but it doesn't have widespread usage yet.

Unfortunately, there will be those platforms that don't conform to the OAuth specification, however we'll certainly look into this further.

Posted

Just pass full $accessToken array, not only $accessToken['access_token'] index. You won't break anything at all and only need to update your handler correspondingly. This was the whole point: protocol is too strict.

Posted
1 hour ago, The Krotek said:

This makes Update Email feature useless (always NULL returned)

That's true. They (VK support agents) told me I can get email address only when authorizing.

1 hour ago, The Krotek said:

and seamless registration impossible (user needs to enter email manually)

You can get email address in _exchangeAuthorizationCodeForAccessToken() method. Just save it as a class property and return it in the authenticatedEmail() method.

Posted
26 minutes ago, Ilya Hoilik said:

You can get email address in _exchangeAuthorizationCodeForAccessToken() method. Just save it as a class property and return it in the authenticatedEmail() method.

This is what I wanted to do, but didn't understand, how can I get this value without rewriting the whole function.

Posted

1. Create new property

	/**
	 * @brief	Email Address 
	 */
	protected $email = NULL;

 

2. Write your own _exchangeAuthorizationCodeForAccessToken(). Note two things. First - use must call the parent method to execute original Invision Community code. Second - email address is not required now in the VK, so it may be empty anyway. Because of this, you need to call isset() to make sure email address is in the response.

	/**
	 * Exchange authorization code for access token
	 *
	 * @param	string	$code	Authorization code
	 * @return	array
	 * @throws	\IPS\Login\Exception
	 */
	protected function _exchangeAuthorizationCodeForAccessToken( $code )
	{
		/* Call the parent to make a request */
		$response = parent::_exchangeAuthorizationCodeForAccessToken( $code );

		/* Save the email. Note that email address may be not provided */
		if ( isset( $response['email'] ) and $response['email'] )
		{
			$this->email = $response['email'];
		}

		return $response;
	}

 

3. And now you can return $this->email. As it is NULL by default (first step), you don't need to make any additional checks.

	/**
	 * Get authenticated user's email address
	 * May return NULL if server doesn't support this
	 *
	 * @param	string	$accessToken	Access Token
	 * @return	string|NULL
	 */
	protected function authenticatedEmail( $accessToken )
	{
		return $this->email;
	}
Posted

_exchangeAuthorizationCodeForAccessToken() function returns the result of _processAccessToken() function and this result is a member array.

Am I missing something here?

Posted

Here's a code:

return $this->_processAccessToken( $login, $accessToken );

The result of access_token endpoint request is $accessToken. You sure it returns this variable, not the result of _processAccessToken() function?

Posted

I really don't understand your question about _processAccessToken().

  • _exchangeAuthorizationCodeForAccessToken() returns $accessToken as an array.
  • _processAccessToken() receives $accessToken as an array.

What's a problem? _processAccessToken() is not something you should touch to.

Posted

Sorry, I mixed it with _handleAuthorizationResponse() function, which returns _processAccessToken() function result. I'll try add an override to _exchangeAuthorizationCodeForAccessToken() tomorrow. Looks like it should work indeed. Thank you.

 

IPS Community framework is a bit confusing to me. I sometimes miss the obvious stuff ?

Posted

I've tested it and assigned email to session variable instead:

\IPS\Session::i()->vkontakte_email

With class variable it didn't work. Probably due to multiple redirection in the process.

This enables seamless registration, but Update Email feature won't work, since email is not returned in user array. But that's OK.

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...