login: admin in python37

270 views
Skip to first unread message

Joshua Smith

unread,
Jan 22, 2021, 1:07:16 PM1/22/21
to google-a...@googlegroups.com
In my quest to figure out how to keep using Google App Engine when Python27 eventually goes away, I've just run into yet another case where something simple seems to have been replaced with a nightmare of complexity.

In my old app.yaml, I had this:

- url: /admin/.*
  script: main.app
  secure: always
  login: admin

Unfortunately, python37 doesn't support login: admin any more (!). I'm facing a mountain of documentation detailing a bunch of different ways I can do authentication now.

Stack overflow is no help at all in simplifying this.

Anyone here have advice on the easiest possible way to get the old Python27 behavior that you have to be logged in as the app administrator in order to hit a certain URL?

This isn't for ensuring crons are only run by cron. That seems pretty easy by looking at headers.

This is for when you have administrative functions that only the developers need access to, and I'm looking for the easiest way to ensure a URL is only accessible to those particular people.

In case it matters, I'm using Flask.

-Joshua

Elliott (Cloud Platform Support)

unread,
Jan 25, 2021, 1:05:47 PM1/25/21
to Google App Engine
Hello Joshua,

I understand that you would like an easy way to implement authentication because you may not continue to use login: admin. I was able to confirm this. First, I would like to apologize for the inconvenience. There is no easy way other than to implement one of the options listed in this document.

You are presented with some options including Firebase Authentication, Google Sign-In and OAuth 2.0 and OpenID Connect. Each of these technologies are described in the document.

I would like your thoughts on the recommended ways so that we may find a solution that agrees with you.

I hope that we may now have enough to elaborate on this discussion.

Joshua Smith

unread,
Jan 25, 2021, 1:21:37 PM1/25/21
to google-a...@googlegroups.com
I'm hoping someone on this list has encountered this, and can say "Yeah, I ran into that. Here's how I dealt with it..."

I'm looking for an easy step-by-step guide to just get the exact behavior that Python 2.7 had.

-Joshua

--
You received this message because you are subscribed to the Google Groups "Google App Engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-appengi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-appengine/05ac62c4-6c44-4e7b-8068-1601d6a4eef0n%40googlegroups.com.

Jose V

unread,
Jan 27, 2021, 11:44:19 AM1/27/21
to Google App Engine
Just in case it helps, you can also easily implement IAP for App Engine. The only drawback would be that it secures the entire application, not specific endpoints, which I am not sure is what you require in your scenario

Joshua Smith

unread,
Jan 27, 2021, 11:49:57 AM1/27/21
to google-a...@googlegroups.com
That does look super easy, but as you pointed out, it applies to the whole app. I just want pages in my /admin section to require auth.

Charlie Engelke

unread,
Jan 27, 2021, 2:13:52 PM1/27/21
to Google App Engine
You can enable and configure IAP independently for different services, so if you can put all the admin functions in a separate service, that could do it.

Joshua Smith

unread,
Jan 27, 2021, 2:28:10 PM1/27/21
to google-a...@googlegroups.com
Interesting. I'll make that my fallback plan if nobody has an idea that simply reproduces the old behavior (which was the exact behavior everyone needed, by the way; why does Google always insist on replacing perfectly good things with insanely complicated things that lack the one thing we all need?)

Emil

unread,
Jan 28, 2021, 10:56:30 AM1/28/21
to Google App Engine
The builtin solution is no longer available, you can test iam permission in your code as explained here if it is feasible for you.

Joshua Smith

unread,
Jan 28, 2021, 11:29:53 AM1/28/21
to google-a...@googlegroups.com
That seems easy enough, but there's something I don't understand. Where does the accessing user's identity come into play?

If I follow the directions the SO answer links to, I end up with something like this:

def adminPermission():
    from googleapiclient import discovery
    from oauth2client.client import GoogleCredentials
    credentials = GoogleCredentials.get_application_default()
    service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)
    resource = "my-project-name"
    test_iam_permissions_request_body = {
        "permissions": [
            "resourcemanager.projects.get"
        ]
    }
    request = service.projects().testIamPermissions(resource=resource, body=test_iam_permissions_request_body)
    response = request.execute()
    return len(response.get("permissions",[])) == 1

But all I'm checking in that code is whether my project has project permission, not whether the user making the request has project permission. If I hit a URL from curl with no auth that is returning True, since of course, my project has permission to get itself.

How do I get the credentials of the user accessing the URL?

-Joshua

methkal

unread,
Jan 29, 2021, 5:08:28 AM1/29/21
to Google App Engine
Hi Joshua,

I will state for you few options here:
1- extract all admin functionality to another app engine service and put IAP in front of it (That's what would I do personaly as it's the most secure and easy one)
2- Create some old fashion login form and test the email and password against some database like datastore before letting any access to admin endpoint
3- use federated auth like firebase auth but this need some more implementation and work from your side. check here https://cloud.google.com/appengine/docs/standard/python/authenticating-users-firebase-appengine

NoCommandLine

unread,
Feb 15, 2021, 1:22:03 PM2/15/21
to Google App Engine
  1. Create an object for a user that you will store in session. This object could have the following attributes - email, isAdmin, userId
  2. Put a login decorator in front of the route. The decorator will ensure (force a login) there is a logged in user before they can access the endpoint (just Google 'python login_decorator' for sample codes)
  3. When the decorator forces a user to login and you retrieve stuff like user email address, check if this email matches the email of the person (or persons) you expect to be your admin. If there is a match, set 'isAdmin' to True, then store the user object in session
  4. After the login decorator code runs, it then moves into the code for your endpoint and there you check if the value of 'isAdmin' is True. If so, you continue processing. If False, you deliver a message to the user and exit

In simple terms, Python37 (which doesn't support 'users api') is forcing you to write some of the code behind the 'login:admin' entry in your app.yaml. The advantage of (doing this hard/extra work) is that you can extend this capability to support people as 'admin' even without a Google Account i.e. you can grant admin privilege to someone based on their twitter login or facebook login or even a manual user Id


..... NoCommandLine ......
If you miss GAE Launcher, try https://nocommandline.com
Reply all
Reply to author
Forward
0 new messages