Running a Globus App without need get an authorizationt token from browser

39 views
Skip to first unread message

Joshua Brown

unread,
May 23, 2022, 2:38:50 PMMay 23
to Discuss
This is similar but slightly different from a previous comment https://groups.google.com/a/globus.org/g/discuss/c/1itrM5rLrcI

I'm wondering if there is a way to run a registered Globus application without having to redirect a user to a browser where they get the access token. This puts a large damper on development cycles if every time I need to run an ephemeral application I have to go through a browser window. 

I know that GitHub and GitLab applications will simply use your client secret, users still have to grant the applications consent the first time they try to access the repo but once granted you don't have to do anything if the app is run again. The onus of keeping the client secret secure falls on the application developer, but it provides so much more flexibility. Is there any way of having something similar?

With the existing set up the only way I can do something similar is to have a daemon always running with a refresh tokens turned on and who simply acts as a proxy to pass messages to globus from the application that is not running continually. 

Stephen Rosen

unread,
May 23, 2022, 3:05:01 PMMay 23
to Joshua Brown, Discuss
Hi Joshua,

Would a client credentials flow not be appropriate for your case? It sounds like a good fit for this.

This example doc could maybe be improved, but the sample at the bottom shows the ClientCredentialsAuthorizer, which I think is the ideal way to use client creds with the SDK:


This is the typical way we recommend handling automated access to Globus APIs.
There's also support for using client credentials via the CLI:


Best,
-Stephen

Joshua Brown

unread,
May 23, 2022, 4:42:39 PMMay 23
to Discuss, sir...@globus.org, Discuss, Joshua Brown
Wow, don't know how I missed that. I think that is exactly what I am looking for. 

Stephen Rosen

unread,
May 23, 2022, 4:58:13 PMMay 23
to Joshua Brown, Discuss
Excellent, great to hear!

One thing I'll point out, which is very important when using this strategy, is that the client credentials use the ID of the client itself, not the ID of any user (admin or otherwise).

That means that if you create a client, and *you* have permissions on a collection, the client does not automatically inherit those permissions.
Instead, you'll have to add additional permissions for your client explicitly.

All Globus APIs for managing permissions support the use of the client ID as an identity ID, so you can also give your client access like any user.
Clients can also join Groups -- using the CLI, this is now pretty easy with `globus group join`, `globus group join --request`, or `globus group invite accept` -- so you should be able to put your client into a Group if you want to use that to manage access.

Of course, let us know if you run into any issues, either here or via sup...@globus.org!
Best,
-Stephen

Joshua Brown

unread,
May 24, 2022, 4:35:24 PMMay 24
to Discuss, sir...@globus.org, Discuss, Joshua Brown
So does this mean I have to have a managed account and subscription on all my personal endpoints in order to use the app/have the app execute a command on my behalf? If so this is problematic.

Michael Link

unread,
May 24, 2022, 5:12:44 PMMay 24
to dis...@globus.org
Hi Joshua,

Globus Connect Personal doesn't support authorization callouts. Another
blocker for that kind of use case is that only the owning Globus
identity has data access to the main collection. Other identities could
only have access via GCP guest collections.

Mike

Michael Link

unread,
May 24, 2022, 5:14:28 PMMay 24
to dis...@globus.org
Sorry about that, this response was meant for another thread.

Stephen Rosen

unread,
May 24, 2022, 5:30:43 PMMay 24
to Joshua Brown, Discuss
Hi Joshua,

Yes, sharing access to a GCP endpoint requires subscription-based features. (Either assigning endpoint roles or using sharing.)
Since a "client identity" is an independent user, using it to automate interactions with GCP would require a subscription.

What we can do and support will depend a lot on what you need in terms of permissions and access -- and I should say that there are some harder limitations on what can be done without a subscription.

I didn't address this before, but in your initial message you say

> With the existing set up the only way I can do something similar is to have a daemon always running with a refresh tokens turned on and who simply acts as a proxy to pass messages to globus from the application that is not running continually.

That sounds slightly overcomplicated to me, with respect to refresh token usage.
After a one-time login flow, you can store your access tokens and refresh tokens in a file -- e.g. use `globus_sdk.tokenstorage` to store them in a JSON file.
After that, anytime you need a token you can construct a RefreshTokenAuthorizer from the file to refresh if necessary and authorize your interactions with the service.

I'd point at the SimpleJSONFileAdapter usage shown in the tokenstorage example as a good starting point:

This is quite similar to how the globus-cli and our other CLI tools operate. Those aren't running continuously, but are able to leverage the level of persistence provided by refresh tokens. I even recall one application which does not use refresh tokens having a "dev mode" which used this kind of behavior to make development faster and easier.

Please let me know if I've misunderstood, or if you want more detail on any part of this. Best,
-Stephen

Joshua Brown

unread,
Jun 7, 2022, 12:57:26 PMJun 7
to Discuss, sir...@globus.org, Discuss, Joshua Brown
This might be a dumb question, so I apologize if it is already in the documentation. Can a user use the Globus transfer API without creating an application client token but instead use their own credentials to authorize an API call, is this supported?

This would get around the permissions limitation of having a user other than the user hosting the Globus Personal Connect endpoint needing access to files on GCP endpoint but being denied.

Stephen Rosen

unread,
Jun 8, 2022, 3:10:28 PMJun 8
to Joshua Brown, Discuss
No need to apologize! OAuth2 is complex, and the spec exposes so many optional extension points, some of which we utilize, that it's very hard to build any generalist knowledge.

There always has to be an application, but it doesn't need to belong to the user.
Have you read through the Globus SDK Tutorial? It seems very well suited to your use-case. The final steps cover using refresh tokens, and in concert with `globus_sdk.tokenstorage` you could write a script which stores and reuses refresh tokens (e.g. in `~/.my-app-tokens.json`).

By way of example, I've attached a sample script which combines the tokenstorage example with the group listing script example.
I'll see about getting this example into our example gallery for the SDK for easy future reference.

Best regards,
-Stephen
list-my-globus-groups.py

Joshua Brown

unread,
Jun 14, 2022, 12:24:57 PMJun 14
to Discuss, sir...@globus.org, Discuss, Joshua Brown
Hi Stephen,

I'm having a little difficulty with following the instructions on this link:  https://globus-sdk-python.readthedocs.io/en/stable/examples/client_credentials.html

When I go to register a Globus application under a project, there is no field for placing the scopes, am I missing something?

" During registration, make sure that the “Native App” checkbox is unchecked. You will typically want your scopes to be openid, profile, email, and urn:globus:auth:scope:transfer.api.globus.org:all."

The image attached is what I see when I try to register an application.

When I try to run the commands provided with my client secret and client id. 

import globus_sdk

# you must have a client ID
CLIENT_ID = "..."
# the secret, loaded from wherever you store it
CLIENT_SECRET = "..."

client = globus_sdk.ConfidentialAppAuthClient(CLIENT_ID, CLIENT_SECRET)
token_response = client.oauth2_client_credentials_tokens()

The last line fails with an error

globus_sdk.services.auth.errors.AuthAPIError: ('POST', 'https://auth.globus.org/v2/oauth2/token', 'Basic', 401, 'UNAUTHORIZED', 'Basic auth failed')



Screenshot (469).png

Stephen Rosen

unread,
Jun 14, 2022, 12:49:21 PMJun 14
to Joshua Brown, Discuss
On Tue, Jun 14, 2022 at 12:25 PM Joshua Brown <joshbr...@gmail.com> wrote:
Hi Stephen,

I'm having a little difficulty with following the instructions on this link:  https://globus-sdk-python.readthedocs.io/en/stable/examples/client_credentials.html

When I go to register a Globus application under a project, there is no field for placing the scopes, am I missing something?

" During registration, make sure that the “Native App” checkbox is unchecked. You will typically want your scopes to be openid, profile, email, and urn:globus:auth:scope:transfer.api.globus.org:all."

The image attached is what I see when I try to register an application.

No, you aren't missing anything. This is an error in the docs!
The page used to have a field for entering scopes, but it was removed. (I can't recall the full history of that field, but I believe it supported a feature which didn't turn out to be as useful as our team originally anticipated.)

Thanks for flagging this.
I'll get the doc fixed right away, but it will take until our next release of the SDK for that to propagate to the `stable` readthedocs site, due to the way that's built.
 

When I try to run the commands provided with my client secret and client id. 

import globus_sdk

# you must have a client ID
CLIENT_ID = "..."
# the secret, loaded from wherever you store it
CLIENT_SECRET = "..."

client = globus_sdk.ConfidentialAppAuthClient(CLIENT_ID, CLIENT_SECRET)
token_response = client.oauth2_client_credentials_tokens()

The last line fails with an error

globus_sdk.services.auth.errors.AuthAPIError: ('POST', 'https://auth.globus.org/v2/oauth2/token', 'Basic', 401, 'UNAUTHORIZED', 'Basic auth failed')


This is hard for me to give you guidance on, as an issue.
The usage you've shown is correct, and quite minimal, but the error indicates that the credentials were somehow invalid.

As a first double-check, I'd suggest
- making sure the client ID is copied correctly, verbatim
- generating a new secret (even if it's temporary) to see if the secret was copied incorrectly
- making sure there is no leading or trailing whitespace on either the client ID or secret

Beyond that, I'm not sure what guidance to offer. You can test the same operation with `curl`, but the SDK is probably easier.

If this continues to be problematic after a "clean retry" to try to correct for anything going wrong with copy-paste, I would recommend filing a support ticket.
It's always possible that there's something unexpected going wrong here.

Best,
-Stephen
Reply all
Reply to author
Forward
0 new messages