Program access admin on GAE - oauth2 - google-app-engine

I have a GAE app, with a URL I restrict to admin:
- url: /admin
script: _go_app
login: admin
I want to PUT or POST to this url with another Go program. What code do I need to write for the client to authenticate to GAE and dev_server.py? Is there a more sensible way that just mocking a web-browser and logging in? I don't need to authenticate or authorise other users, just the admin account for that app.
Is this OAuth? OAuth2? OpenID? Federated? Something else?
I realise this is a bit of an awkward question, since I'm not even sure what the right way to ask it is. However I am able to post to (in this example) /admin using a web browser after logging in with my (admin) gmail account. In that case the request (sent by Chrome) contains the cookies: __cfduid, ACSID (and what I think are Google Analytics IDs). Presumably one of those is responsible for my authentication. How do I get one of those?
And as a side question, if someone MITMs my connection (over http), can they hijack my admin session by reusing that cookie?

GAE likes OAuth2
Have a look at goauth2 . It seems to be the canonical OAuth2 library for Go. They provide a fairly comprehensive example at https://code.google.com/p/goauth2/source/browse/oauth/example/oauthreq.go .
With regards to your question "Presumably one of those is responsible for my authentication. How do I get one of those?", they state:
To obtain Client ID and Secret, see the "OAuth 2 Credentials" section under
the "API Access" tab on this page: https://code.google.com/apis/console/
And, finally, my humble opinion on "if someone MITMs my connection (over http), can they hijack my admin session by reusing that cookie?" is that you should never provide any authenticated connection (nor the connection that does the authentication) over plain http. Especially an admin section.
EDIT: To elaborate on the MITM question, make sure you use HTTPS for any login requests and subsequent requests for the same session, and make sure to set Secure and HttpOnly flags on your cookies.

OAuth2 if you want to use Google Accounts.
See here for details: https://developers.google.com/appengine/docs/go/users/overview (this section specifically deals with admin views)

Related

AAD reply url is flagged by WAF in Azure

I have enabled the Web Application Firewall in the Azure FrontDoor with the default policy with the detection mode.
In the logs generated by the WAF, we can see the firewall is marking the reply url set in AAD with action as Block.
I believe the firewall is detecting this as threat.
Since the url is required for the working of AD authentication, what can be done to ensure the security ?
Or this can be ignored ?
Go to your WAF policy of Front Door WAF policy and click Managed rules. Collapse all and click the related policy and change action to Allow. Then refresh the WAF in front door, it will apply.
You could custom rules for WAF with Azure Front Door and refer to the disable rule in app gateway to fix false positives.
You shouldn't need the reply URL to properly as it's really only required to get the access token. If you're getting the access token and you don't need access to the reply url, this shouldn't be something you need to worry about.
If you would like to get to the reply url for purposes of your application, you could unblock it, but there shouldn't be any security issues assuming you know that the reply url is secure.
Per the docs : https://learn.microsoft.com/en-us/azure/active-directory/develop/reply-url
A redirect URI, or reply URL, is the location that the authorization server will send the user to once the app has been successfully authorized, and granted an authorization code or access token. The code or token is contained in the redirect URI or reply token so it's important that you register the correct location as part of the app registration process.

Using Multiple Angular App and Session Management

I have 4 angular applications one is a landing app which asks user to login and has to redirect the user according to its type
to one of the other 3 applications. I am unable to figure how to should i achieve that.
Have the three apps running on different subdomains. Upon login backend send a redirect response, figuring out what type of user it is?
But this leads to cors Error. Also i am not sure whether the cookie which i am setting will be accessible in all the subdomains or not.
Is there a way out?
You can do a redirect, but it seems like an unnecessary step (and kind of convoluted for this type of application).
Instead of returning a redirect based on login, it seems more straightforward to just return the address you want to redirect to in the response. Trigger a lookup to determine which app you should be directing to (however you're doing that) and then return the address of the app in the response data. From within Angular, you can extract the address from within response.data in $http. (see angular docs). The nice thing here is you also keep routing control and knowledge of state within Angular itself.
As for the apps themselves--instead of a subdomain, you can simply put the apps into different folders on your domain. This deals with CORS and the cookie issue.
Otherwise, you'd need to set a CORS header. You would do this on whatever backend you're sending the requests to--there's usually some sort of library to make it easy, for example, Flask CORS for Flask. If you need to share cookies in this case, this StackOverflow answer discusses one way of doing it (using an intermediary domain).
Generate a security key for the user session with some TTL in an authentication table when you authenticate the user with your App1
Redirect the user to any other app in any domain with this security key where they can query the authentication table and verify the user.
Let these other applications work on their own (in the front end) and communicate with the back-end with the security key when necessary.
Lot of PHP frameworks has built-in support for this mechanism. My favorite is Silex.

appengine http secure?

A simple question, I think.
If I use the google users accounts in appengine
from google.appengine.api import users
to authenticate my users, how secure is the rest of my app under http (not https), ie. where are the weak points of such a setup?
Thanks
Assume that anything you send over http can be intercepted and examined by an attacker. This includes whatever token you are storing in their browser to authenticate them - the attackers can see this too, and use it to fake requests.
If this sounds like a "theortical" vulnerability that you don't need to worry about, then you shouldn't do anything that involves safeguarding user data until you read up on FireSheep and understand how it works and how you would prevent something similar. (This is just one example of an attack you need to understand. It is not the only possible attack.)
In short, the weak points of such a setup are all the points where you are using http to send anything you want to keep private.
Your question is unclear, but if you're asking whether authenticating users with Google Accounts on an HTTP app could potentially expose passwords to an attacker, the answer is no.
Even though your app is not using SSL, passwords are never transmitted in plain text. When authentication starts, users are redirected to a secure page at google.com to enter their credentials. Credentials are posted via SSL, and if authentication succeeds, Google generates an authentication token that is passed back to your app and stored in a cookie. The Users API makes an internal RPC to resolve this token back into Google credentials.
The most that an attacker could do is intercept the authentication token and spoof the user for the duration of the token's validity (1 day by default; configurable up to 2 weeks). They would never have access to passwords. To prevent spoofing, you'd need to make sure all logged in activity happens on HTTPS and the auth cookie is never stored via HTTP.

CakePHP 1.2.6 Login redirects to SSL but need to log in again

On a CakePHP 1.2.6 site, I performed the suggestions in http://bakery.cakephp.org/articles/view/how-to-bend-cakephp-s-session-handling-to-your-needs.
The problem I'm running into is after logging in from http, the site refreshes back to the home page at https and does not show that I'm logged in. I need to log in again and then it works.
How can I fix this? Using the Auth component by the way.
There is often little point in using HTTPS if you're transferring your logged in state from an HTTP connection to an HTTPS connection: someone eavesdropping the HTTP communication could then impersonate the legitimate user using HTTPS. (This is what secure cookies are for too.)
Going from HTTPS to HTTP can be OK if you just want to protect entering the user's password, but you should always avoid to go from HTTP to HTTPS without re-challenging the user, otherwise, the communication won't be more secure than if it was done over HTTP with respect to its authentication.
You need to login from HTTPS protected location. Here is a great little component that will force SSL on the login (or anywhere else in your code).
http://bakery.cakephp.org/articles/view/component-for-forcing-a-secure-connection

App Engine remote_api with OpenID

I've recently tried to switch my app engine app to using openID, but I'm having an issue authenticating with remote_api. The old authentication mechanism for remote_api doesn't seem to work (which makes sense) - I'm getting a 'urllib2.HTTPError: HTTP Error 302: Found', which I assume is appengine redirecting me to the openid login page I've set up.
I guess I'm missing something fairly obvious. Currently my remote_api script has the following in it -
remote_api_stub.ConfigureRemoteDatastore(app_id=app_id, path='/remote_api', auth_func=auth_func, servername=host, secure=secure)
where auth_func is
def auth_func():
return raw_input('Username:'), getpass.getpass('Password:')
Any ideas what I need to supply to remote_api? I guess similar issues would be encountered with bulkloader too. Cheers,
Colin
This was a fun one.
Looking at remote_api, the flow for authentication seems to be something like this:
Prompt the user for Google credentials
Post the credentials to https://www.google.com/accounts/ClientLogin
Parse the auth token out of the response body
Pass the token to https://myapp.appspot.com/_ah/login
Grab ACSID cookie set in the response
Pass the ACSID cookie in subsequent requests that require authorization
I couldn't find a lot of documentation on the new OpenID support, though Nick's blog entry was informative.
Here's the test app I wrote to see how things work:
app.yaml:
handlers:
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
- url: /.*
script: test.py
test.py:
class MainPage(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if user:
self.response.out.write("Hi, %s!<hr>admin is %s" % (user.user_id(),
users.is_current_user_admin()))
else:
self.redirect(users.create_login_url('/', None,
'https://www.google.com/accounts/o8/id'))
Flipping my auth mode between Google Accounts and Federated Login, I noticed a few things:
Admin users are correctly recognized by is_current_user_admin() with OpenID
Mixing modes doesn't work. With authentication set to Google Accounts, calling create_login_url with a federated_identity throws a NotAllowedError
An ACSID cookie is still produced at the end of the login process, only it comes from /_ah/openid_verify instead of /_ah/login
So what's happening with remote_api when using Federated Login? If we're using the default appengine_rpc.HttpRpcServer, it's dutifully following the same Google Account authentication process described at the top, only the app no longer considers the ACSID cookie returned by /_ah/login to be valid, so since you're still unauthenticated, you get a 302 redirect to the OpenID login page, /_ah/login_required.
I dunno what the right solution is here. Seems like it would require an API update. Maybe Nick or one of the other Googlers can weigh in.
For now, here's a hacky workaround:
Turn on Federated Login for your app
Make sure you're passing save_cookies=True when calling remote_api_stub.ConfigureRemoteDatastore for your console script
Attempt console authentication and get the 302 error
Login as an admin via your app's web interface
In your browser cookies, find the ACSID cookie for myapp.appspot.com
Find and edit your local ~/.appcfg_cookies file
Replace the ACSID cookie for myapp.appspot.com with the one from your browser
The next time you try to use remote_api, it should work without prompting for credentials. You'll have to repeat the last 4 steps every time the cookie expires, though. You can bump the expiration from 1 day to as high as 2 weeks in the admin console to minimize the annoyance. Have fun!
This is definitely an issue... mark your interest in getting Google to fix this by starring the ticket at http://code.google.com/p/googleappengine/issues/detail?id=3258 and feel free to add any of your workarounds there.
On a related note, we also recognize that the docs are somewhat sparse, so I'm working on an article which hopefully fills-in some of those holes... stay tuned and keep your eyes open at http://code.google.com/appengine/articles
Here's a workaround you can use until there's a more permanent solution in place.

Resources