← Back to team overview

ubuntu-phone team mailing list archive

Re: [Scope] More authentication questions

 

> On 19 Nov 2014, at 2:09 AM, Robert Schroll <rschroll@xxxxxxxxx> wrote:
> 
> Hi all,
> 
> I'm completely confused about how I should handle authentication over the life of my scope.  I'll try to explain my specific problems below, but if you think it's best to ignore those and give me an overview of the recommended approach, that'd be great too.
> 
> My scope [1] uses Google oauth2 for authentication, and can't do anything meaningful without it.  I followed the example from the API documentation and authenticate in the Query::run() function.  I store the key for later use, as I hit the Google servers from other places from the code.
> 
> This works fine for a while, but if the scope is open for long enough, eventually Google will reply with a 401 Invalid Credentials response.  I assume there's only a limited validity to the key I get.  I could detect this response and then re-run the authentication, but
> 
> 1) It'd be better to know that the key was expired before hand.  Is there any way to know this?
> 
> 2) The logical place to put this check would be inside my get() method, my post(), method and my batch() method.  But this is already getting redundant, and I'm not sure what to do when authentication fails.  Right now, the check is in the Query::run(), so I can run oa_client.register_account_login_item().  Is it better to handle the oa_client close to the network or close to the UI?

Its really up to you where you want to query the oa_client. Once the OA backend has requested and given you an access token, subsequent calls to retrieve statuses from oa_client will have negligible overhead (In fact, even re-instantiating a new OnlineAccountClient object on every query will have negligible overhead as its actually the OA backend that caches the token).

Therefore, the easiest, stateless way to do this is to simply construct a new OnlineAccountClient object everywhere you need the token (as shown in the API example). This way it doesn’t matter what state your scope is in / was in, and you’ll always guarantee an up-to-date token. The OnlineAccountClient class was designed to construct and destruct efficiently for this very purpose.

> 
> I've also heard that scope needs to handle being killed at arbitrary times,

A scope will only be terminated if no comms are exchanged for 40s (comms = pushing a result, receiving a query request, etc. Anything over the wire), at which point your Scope::stop() method will be called. Bare in mind however, that a query can be stopped by the user at arbitrary times. In this case, you will receive a call to your Query::cancelled() method. Be sure to handle this callback accordingly (clean up, etc.).

> which presumably means it may start up in an arbitrary state.

Not sure I understand what you mean “start up in an arbitrary state”. The scope will simply start again from fresh (i.e. a fresh process is started). If you need to store persistent state between your scope stopping and starting, you can store something to your scope’s cache directory in your Scope::stop() method, then retrieve it again in your Scope::start() method. Your cache directory path can be retrieved by calling cache_directory() (a method on ScopeBase) from your Scope class methods.

> (I think this is suppressed when running from Qt Creator, right?)

Right, this allows you to sit on a breakpoint / step through code without the scope dying on you.

> This complicates the issue further, since now I have to guard each API access against authentication, not just the "first" in the standard workflow.  (This may make worries about expiring keys moot, though.)

Right, so like I said, if you need to check the state of your access token on every call to the API (i.e. just construct temporary OnlineAccountClients wherever needed), then that should not effect your scope’s performance. Its best to write your scope as state-less as possible anyway.

> How to do you handle authentication failures that could occur anywhere? Are there best practices documented somewhere, or am I on my own?

So yeah, wherever in your code you could expect an authentication failure, you’ll need to handle it there and then. I’m not sure I understand what you mean by anywhere though. Can you give me an example of a point where you could get an authenticating failure that would leave you in an unrecoverable state?

> 
> Thanks,
> Robert
> 
> [1] https://github.com/rschroll/gmail-scope
> 
> 
> -- 
> Mailing list: https://launchpad.net/~ubuntu-phone
> Post to     : ubuntu-phone@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~ubuntu-phone
> More help   : https://help.launchpad.net/ListHelp



Follow ups

References