For security reasons we do not plan to allow that.
>
> On Monday, December 12, 2011 1:07:32 PM UTC-8, hemp wrote:
>>
>> We would like to have the ability to request a refresh_token without
>> forcing a user approval request.
--
--Breno
1. Asking for offline access doesn't automatically provide a user
dialog if the user has previously approved non-offline access to the
same scope
2. Auto-approve doesn't provide a refresh_token, even if the user has
approved offline access
1 is an issue purely because it's not obvious to the developer. It's
not a huge deal because if we're doing offline access, we not actually
sending the user back through the auth endpoint, so we can get around
this by just always specifying the force option. It's just that we
have to know to do this, and it seems weird.
2 is the problem hemp is discussing, which is the other side of the
same coin. It shouldn't actually come up in production, because once
you have offline access, you should have a refresh token and you
shouldn't ever hit the auth endpoint. But for dev/test work it's a
huge hassle, since a we'd typically reset our databases, losing our
persisted refresh tokens. To get them back, we have to add the force
option. At a higher level, it's a really confusing API contract:
sometimes the auth endpoint provides a refresh token and sometimes it
doesn't, and the variable isn't the permissions being requested, but
rather whether the user has previously approved the request.
Generally, I think it's much simpler if auto-approval provides the
same data to the app as click through. You say you don't plan to allow
that for "security reasons", but that doesn't make any sense to me;
either the user has approved offline access or she hasn't.
My conclusion from both items is that it's necessary to always specify
approval_prompt=force when requesting offline access, or else you get
really inconsistent results. If you guys are sticking to that model,
then why not just make requests for offline access *always* show the
dialog? That's not my ideal, but it would be simpler for everyone, I
think.
To make our server in sync with our test servers, you should revoke
the tokens in the server. That's what we'd hope you do in production
too if the user choose to 'de-authorize' in your site.
> To get them back, we have to add the force
> option. At a higher level, it's a really confusing API contract:
> sometimes the auth endpoint provides a refresh token and sometimes it
> doesn't, and the variable isn't the permissions being requested, but
> rather whether the user has previously approved the request.
> Generally, I think it's much simpler if auto-approval provides the
> same data to the app as click through. You say you don't plan to allow
> that for "security reasons", but that doesn't make any sense to me;
> either the user has approved offline access or she hasn't.
refresh_tokens are like scoped passwords. Issuing them transparently
without user intervention is a significant security risk, whether or
not users approved the application.
>
> My conclusion from both items is that it's necessary to always specify
> approval_prompt=force when requesting offline access, or else you get
> really inconsistent results.
Not really. See below.
> If you guys are sticking to that model,
> then why not just make requests for offline access *always* show the
> dialog? That's not my ideal, but it would be simpler for everyone, I
> think.
There are some cases (e.g., when the user is signing into the
application and granting authorization at the same time), where it's
impossible for the app to decide ahead of time (because it doesn't
know the identity of the user yet) whether this is a first approval,
or subsequent auto-approval. Also in this case it's fundamental that
auto-approval works (a prompt always for login is an unnacceptable
user experience).
>
> On Dec 12, 5:19 pm, Breno de Medeiros <br...@google.com> wrote:
>> On Mon, Dec 12, 2011 at 13:12, hemp <sh...@hempel.cx> wrote:
>> > To clarify my request:
>>
>> > In the case where a user has already granted approval for offline access and
>> > a refresh_token has already been provided, we still desire the option to
>> > request a refresh_token without forcing an additional approval prompt.
>>
>> For security reasons we do not plan to allow that.
>>
>>
>>
>> > On Monday, December 12, 2011 1:07:32 PM UTC-8, hemp wrote:
>>
>> >> We would like to have the ability to request a refresh_token without
>> >> forcing a user approval request.
>>
>> --
>> --Breno
--
--Breno
Right, that's exactly the problem: if I don't know whether the request
is going to be auto-approved or not, I don't know whether or not I'm
going to receive a refresh token. Again, that can be worked around,
but having the the oauth endpoint respond differently based on a
variable the app has no access to is a difficult interface.
On Dec 12, 6:23 pm, Breno de Medeiros <br...@google.com> wrote:
I meant this as an example why access_type=offline does _not_ imply in
approval_prompt=force; Some applications will want to use both. Some
will only want to use access_type=offline (I expect this to be the
more common situation, actually). In the vast majority of the cases,
this causes no real issues in production, as the default behavior is
exactly what the application needs.
--
--Breno
One thing you mentioned is that in testing, I should be revoking
access for the user instead of forcing the dialog. That makes sense,
but is there a way to do that programmatically, or do I have to do
that from the user's account settings page?
On Dec 12, 7:21 pm, Breno de Medeiros <br...@google.com> wrote:
Yes, programmatically you can use the revoke endpoint. Using POST:
curl "https://accounts.google.com/o/oauth2revoke" -d
"token=$refresh_token_to_revoke"
--
--Breno
Sorry, there was an error of cut-and-paste in my response. Should be:
curl "https://accounts.google.com/o/oauth2/revoke" -d
"token=$refresh_token_to_revoke"
i.e., the revocation endpoint is accounts.google.com/o/oauth2/revoke
(notice the '/' between 'oauth2' and 'revoke')
--
--Breno
On Dec 12, 8:45 pm, Breno de Medeiros <br...@google.com> wrote:
> On Mon, Dec 12, 2011 at 17:42, Breno de Medeiros <br...@google.com> wrote:
>
It would be edifying for the community if you could explain the
security implications of this. Which weakness in your authentication
scheme would a system exploit in order to request a refresh_token that
doesn't belong to them?
I will give a counter example. I know you folks and Facebook don't see
eye to eye on much, but Facebook's OAuth implementation does not use
refresh tokens and not only is it possible, but the normal case, that
they return auth tokens for offline access without prompting the user
again for approval. I'm actually not aware of any OAuth2
implementation except Google's which refuses to grant an offline auth
token for a logged in user without force-prompting them. The OAuth v2
(22) spec lists refresh tokens themselves as optional (ie: not a
security risk.)
This strikes me as a somewhat arbitrary decision. To dismiss our
requests to change it for unexplained "security reasons" seems odd.
Thanks for your time. I do appreciate that you are monitoring and
responding to this thread. Ultimately we are beholden to your
implementation; I simply prefer if usability prevails over presumption
in API design.
Your main consideration is that you'd like to share authentication
state between a web application and a native application. Is that
correct?
--
--Breno
I am sorry for how things played out with our application. We
announced these changes in the blog and in this mailing list on Nov.
10: https://groups.google.com/forum/#!searchin/oauth2-dev/just...@google.com/oauth2-dev/_kqhtqqCbLg/XzgyAHGEASwJ
; It may have been too late for your application or you may have
missed the announcement.
Note that Google's OAuth2 API will soon leave the "Experimental"
status and that means more predictability moving forward.
--
--Breno
I am sorry for how things played out with our application. Weannounced these changes in the blog and in this mailing list on Nov.
10: https://groups.google.com/forum/#!searchin/oauth2-dev/just...@google.com/oauth2-dev/_kqhtqqCbLg/XzgyAHGEASwJ
; It may have been too late for your application or you may have
missed the announcement.
Note that Google's OAuth2 API will soon leave the "Experimental"
status and that means more predictability moving forward.
Which part of that is causing lots of work? Is it storing the refresh token?
On Wed, Dec 14, 2011 at 3:51 PM, Justin Smith <just...@google.com> wrote:Which part of that is causing lots of work? Is it storing the refresh token?Our specific scenario is slightly different:a) UserA kicks off the flow as part of the authentication to our web app. User sees consent page.b) Web app exchanges the authorization code & receives a refresh token.
c) Web app authenticates to our backend service using the refresh token, which stores it for future use.... time goes by ...d) UserA returns to our web app & kicks off the same flow. No consent reqd.e) Web app exchanges the authorization code for an access token.f) Our backend service expects a refresh token in order to authenticate the user, but we don't have one.Step f is where it breaks down in our environment. Because we assumed a refresh token would be available, the auth system was built to expect it. We would have to modify our backend service to support optionally taking an access token.What we would probably end up doing eventually is to have the backend service accept an access token, use it to fetch user details, then use those details to identify the user in our database and associate an existing refresh token with it. The problem being, of course, that we then have to handle a bunch of scenarios like expired refresh tokens, etc etc.
That isn't an issue if we have a valid refresh token to begin with; so the "a lot of work" it causes is not so much in coming up with a solution but getting the right people involved in making the changes and then identifying and handling all the ways it might fail.
The Web app should not be exchanging the authorization code; this implies that you're exposing the client_secret to end users. The backend service should exchange the authorization_code.
The problem being, of course, that we then have to handle a bunch of scenarios like expired refresh tokens, etc etc.Refresh_tokens do not expire.
Thank you for your feedback Breno. I've addressed your comments below - but I want to add that you got on my case earlier for getting off topic and now you're attacking our application (based on assumptions) instead of addressing my request.
I only shared what I shared because Justin asked and I thought it might help demonstrate that your view of how these APIs are being used may be incomplete; not to open a dialog about our system architecture.
- ShawnOn Thu, Dec 15, 2011 at 10:40 AM, Breno de Medeiros <br...@google.com> wrote:
The Web app should not be exchanging the authorization code; this implies that you're exposing the client_secret to end users. The backend service should exchange the authorization_code.The web app uses the server side flow to authenticate the user; the client secret is never exposed to end users or anyone else. We don't involve our backend service until the user has been authenticated by Google and has authorized our app to call APIs on their behalf. We also have an iPad client which uses the client side work flow and the backend service must accommodate both.
The problem being, of course, that we then have to handle a bunch of scenarios like expired refresh tokens, etc etc.Refresh_tokens do not expire.That may be the covenant you've made, but we have to treat all promises as breakable - as evidenced by the recent change to stop returning refresh tokens. It was only meant as an example.
a) UserA kicks off the flow as part of the authentication to our web app. User sees consent page.
b) Web app exchanges the authorization code & receives a refresh token.
c) Web app authenticates to our backend service using the refresh token, which stores it for future use.
... time goes by ...
d) UserA returns to our web app & kicks off the same flow. No consent reqd.
e) Web app exchanges the authorization code for an access token.
f) Our backend service expects a refresh token in order to authenticate the user, but we don't have one.
Step f is where it breaks down in our environment. Because we assumed a refresh token would be available, the auth system was built to expect it. We would have to modify our backend service to support optionally taking an access token.
What we would probably end up doing eventually is to have the backend service accept an access token, use it to fetch user details, then use those details to identify the user in our database and associate an existing refresh token with it. The problem being, of course, that we then have to handle a bunch of scenarios like expired refresh tokens, etc etc. That isn't an issue if we have a valid refresh token to begin with; so the "a lot of work" it causes is not so much in coming up with a solution but getting the right people involved in making the changes and then identifying and handling all the ways it might fail.
I am trying to understand how you use our APIs so that I can give you appropriate advice. Didn't mean to sound antagonistic.
Glad to hear I was mistaken in understanding how your web app is architected. This brings back the point earlier of why I didn't want to give detailed examples of threats and attacks earlier.
The client-side flow is, I presume, one time and in the future the client uses the refresh_token to authenticate to your server, right? The client-side flow assumes offline access (it was not affected by these changes).
In the past, there was no auto-approval of code requests; so as you architected your application, all users had to approve access on every sign-in (before and after the change). The current changes enable auto-approval and better user experience but require you to take a different way to structure your code.