-
Notifications
You must be signed in to change notification settings - Fork 26
Support for hybrid server-side flow (one-time codes) #5
Comments
The hybrid flow and |
/sub |
Related to having access to the code that can be sent to the server, on the server side you would need methods for Additionally a very common scenario for this flow is to save the refresh token obtained from the code exchange on the server side in order to be able to perform tasks on behalf of users while they are offline. This would use To use it, it would be necessary to have something like |
This seems to be a G+ only Sign in flow. The apps get also registered under https://plus.google.com/apps (normal apps get added to https://security.google.com/settings/security/permissions). So far we only intended to implement OAuth2 flows from https://developers.google.com/accounts/docs/OAuth2. Though it might make sense to add the G+ flow as well. We'll discuss this more. |
Very good point. We currently don't have server flows, but there is already a TODO in the code :)
Correct. You could just save the (user-id, AccessCredentials object)-tuple to the DB. It is beneficial/important to add not just the refresh token because:
You could read the (user-id, AccessCredentials)-tuple from DB. If the AccessToken is still valid, you just use it, otherwise it needs to be refreshed. There is already an autoRefreshingClient(ClientId, AccessCredentials, http.Client), which handles this under the hood. There is also a refreshCredentials(ClientId, AccessCredentials, http.Client) if you want to do refresh manually. |
@mkustermann I'm currently working on an app using hybrid flow as described. It does not get an entry in G+, only under account permissions as expected. I currently do auth.callMethod('authorize', [new js.JsObject.jsify({
'client_id': clientId,
'scope': scopes.join(' '),
'immediate': immediate,
'response_type': 'code token id_token',
'login_hint': loginHint,
'cookie_policy': 'single_host_origin'
}), (js.JsObject jsResponseObject) { If successful it returns access_token, code and id_token (and several other params of course). Note: Cookie_policy allows Google to display the account chooser. Login_hint helps immediate logins, when there are multiple accounts to choose from. The resulting code is then sent to my backend API which exchanges it with Google's OAuth API for an access_token (and refresh_token if required and allowed) for the server to use. I only have a single client id registered on the developers console (Client ID for web application), and only the backend API knows and uses the client secret. |
@taisph Thanks for the info. I've read this on the gplus web signin page where the hybrid flow is also described. If this is a feature of the normal gapi.auth and not of the G+ specific one, we're more than happy to include the hybrid flow in this package. I'll try to reach out to people working on this and see if this is supported -- because as you mention, it doesn't seem to be documented here In case you would like to contribute to the googleapis_auth package, I'm happy to pull changes. (See Google Contributor License Agreement for the formalities.) |
The "one-time code flow" is something that used to be specific to G+-sign-in, but the g+-signin flow has since been extended to be the general/preferred "Google sign-in" solution. The See https://developers.google.com/accounts/docs/OAuth2WebServer for all supported OAuth parameters. The special "hybrid" flow is just a special implementation of the web-server flow by using The important parameter for the code flow is
|
I've spent more time looking into this and implemented a version of the hybrid flow in 8350d4a . Though, this hasn't been published on pub yet. // client
client sends "auth code" somehow to the server: // server
We currently do not plan to handle "ID Tokens". Doing so would at least require code for verifying claims issued by the google endpoint. Comments welcome -- it's not on pub and we can change the API if you've better suggestions. |
I tried it but I run into a weird problem
but when I navigate to the function using ctrl+click the method is shown. |
I had to change the path dependency to a git dependency. |
Would be nice if |
I wrote a simple Google JWT claim decoder/validator (id_token; see link below). It still needs certificate signature validation but I haven't had the time to add this yet as the base JWT handler (dart_jwt) is still missing proper support for RS256. It does however validate the access token and code using the hashes provided in the JWT. |
|
Getting a If the refreshToken gets "lost" at some point, the only way to get a new one is to call authentication with |
Hi Gerwin, thanks for your reply. |
As I said, you only get a refreshToken on the very first code-exchange for a user. If you have authenticated before any future code-exchanges won't include the refreshToken. |
I don't get it. I send the code to the server and the server requests the token. How is that not the first code-exchange? |
When you sign-in, do you see a consent screen, or do you get logged in automatically? |
The easiest way to test is to revoke permission for your client ID from https://security.google.com/settings/security/permissions and then try again. The proper way would be to add an The complete hybrid-flow would look like this:
|
Eine schwere Geburt ;-) |
Best to open an issue for this. I guess the reason it is not yet supported, is that no-one needed it so far :) |
@mkustermann |
[Sorry for the high latency, I've been on vacation for some time ...] @zoechi About "force: true": Our discussion was about whether we should expose both flags, "immediate" and "force", or have only one boolean which switches between immediate=true/force=false and immediate=false/force=true. @Scarygami Since you have experience in this area, can you think of a case where immediate=false/force=false provides any additional value? |
Actually immediate=false/force=false is the most common scenario you will use on your website, connected to a sign-in button. The first thing you do is try a flow with immediate=true/force=false without any user-interaction to allow automatic login if you want to have that. immediate=false/force=true is actually something you would want to avoid, the only reason for this is if you have lost the refresh token and need users to sign-in again with consent-screen to get a code that allows you to retrieve a refresh token. For users who have signed in with your app previously this will create a rather confusing consent screen requesting only "offline access" because incremental auth doesn't display already granted permissions. |
Thanks Gerwin for the explanation. CL is up for review to fix the force flag and add the immediate flag as well: |
Looks good to me anyway :) |
We were already doing the right thing before in the normal flow -- but I've renamed the forceUserConsent to immediate -- because this is what it was actually doing. immediate=false/force=true only make sense for offline access and we have the hybrid flow for that now. Committed in ffbb5de & published googleapis_auth:0.2.0 on pub. |
Great, thanks! |
It would be nice if support for hybrid flows could be added. When a client authenticates with Google, it receives both an access token and a code which the client then sends to the client's server, who then exchanges that code directly with Google's servers to get its own access token. More secure than sharing the access token as you need the client secret to exchange the code server-side.
It seems like you can set
response_type='token code'
when callinggapi.auth.authorize
to achieve this but I haven't found it explicitly documented.Flow:
Using the Google+ signin button for the hybrid flow:
https://developers.google.com/+/web/signin/server-side-flow
The text was updated successfully, but these errors were encountered: