HTTP authentication in App Engine Dev Server - google-app-engine

I want to setup the App Engine Dev Server, so that it's available to other people for a preview.
What I'd really like to do before that is enable HTTP authentication for any URL served from that site. I don't want anyone to access the service without passing that stage. I could, of course, build my own HTTP authentication into the app I'm developing, but that's not a perfect solution, because I don't need that feature when the app is deployed.
Is there any good way to solve it?

Are you using Java or Python?
If you're using Python, you can use existing WSGI middleware to handle HTTP basic auth. Here are some options:
paste.auth.basic
barrel
AuthKit
wsgiauth

Deploy the app to the appengine servers, but use a different app id than the one you will eventually use in production. That way you don't have to develop any extra authentication mechanism, and you don't have to worry about how well the dev app server will handle multiple users worth of load.

Don't make the dev_appserver publicly accessible. It's not designed for it, and it's not secure. To name just one problem, any visitor can go to yourhost/_ah/admin/ and mess with your datastore, and the auth suggestions by lost-theory won't prevent it.
If you absolutely must do this, set up Apache or another webserver as a reverse proxy, implementing authentication and blocking access to /_ah URLs. Peter's suggestion of deploying it to App Engine is a much better one, however.

Here's a pretty solid implementation I came up with
Through my search, I found tons of sloppy/incomplete implementations of BasicAuth for GAE online. As a result, I ended up writing my own. This is the best/simplest approach I have been able to come up with so far.
I consider it a 'good practice' to keep request handlers as thin as possible. To cut down on boilerplate and copypasta in the handlers themselves I decided to implement authentication as a decorator. To use it just attach the decorator to the handler's get/post/put/delete methods.
For example:
from decorators import basic_auth
class Handler(webapp2.RequestHandler):
#basic_auth
def get(self):
# load your page here
Then add the decorator to decorators.py:
import base64
import os
from webapp2_extras import security
import yaml
def basic_auth(func):
def callf(webappRequest, *args, **kwargs):
# Parse the header to extract a user/password combo.
auth_header = webappRequest.request.headers.get('Authorization')
# if the auth header is missing popup a login dialog
if auth_header == None:
__basic_login(webappRequest)
else:
(username, password) = base64.b64decode(auth_header.split(' ')[1]).split(':')
if(__basic_lookup(username) == __basic_hash(password)):
return func(webappRequest, *args, **kwargs)
else:
__basic_login(webappRequest)
return callf
def __basic_login(webappRequest):
webappRequest.response.set_status(401, message="Authorization Required")
webappRequest.response.headers['WWW-Authenticate'] = 'Basic realm="Secure Area"'
def __basic_lookup(username):
accounts_file = os.getcwd() + os.sep + 'app' + os.sep + 'accounts.yaml'
stream = file(accounts_file, 'r')
for account in yaml.load(stream):
if account['username'] == username:
return account['password']
def __basic_hash(password):
return security.hash_password(password, method='sha1')
Note: Double underscore prefixed are used here on functions that shouldn't be visible outside of the 'decorators' module.
In this case, a failed login attempt will simply popup another login dialog, I'm authenticating using a password that is stored in a separate accounts.yaml file, and the passwords are stored in a SHA1 hashed form.
The code is written to be easily customized:
Modify __basic_lookup() if you need your passwords are stored somewhere else (ex database).
Modify __basic_hash() if your passwords are plaintext or encoded using a different method.
Modify __basic_login() if you want a different response to a failed login attempt. Such as an artificial delay to prevent brute-force attacks, or a redirect.

Related

How to correctly store secret keys on React App?

I was happy lasts days using **.env **file with the npm dotenv package and saving there some secret keys i use on my React App...
On my first test opload I noticed that my webbApp runs ok EVEN without specifying the .env secret keys on the sever...
So then, was obious to feels like the secret keys are anywhere on the public files (and yes)
I was looking what im doing wrong, and found many documentation (official) that says literally:
WARNING: Do not store any secrets (such as private API keys) in your React app!
Environment variables are embedded into the build, anyone can view them by inspecting your app's files.
official doc here if anyone is looking for more info
After 3 or 4 heartAttacks I write this to ask for help on this concept problem.
Anyone knows some documentation where i can read and understant HOW to correctly save sercret keys on this kind of apps (react apps) ?
why the hell is not like all time backend .env files ?
Some info I found, says something about to serve the secret key ontime from another server.
And... sounds stupid for me, i mean: Ok, i can do that but.. its just stupid cause then:
or server will serve the sercret keys "free" vía GET or something like this without no-login-needed.
or webbApp would need a secret_login_key to login and get the secret key <- in this case, where to store that secret_login_key ? its a infinite bucle ? XD
So:
it is posible.. (of course it is) so TRULY store secret keys on React App ? but where and how ?xD
what's the way you store the secret keys on ur react App and u are proud of it?
of course the login typing from keyboard user/pass its the "easyway" to have or not have access tho private information but.. what if i need this to be automatic from my webApp ?
Thanks.
For automatic access to your webapp from the frontend (React), you need a bearer token that is stored in localstorage (bad idea) or as a cookie of the user's browser. Popular example of bearer token is JWT token.
This is how you generate a bearer token on the user's browser: by using Universal Login (login with Google/Fb/Github/Twitter etc) to a provider like Auth0.
React has to communicate with Auth0, Auth0 will authorise the user and return a bearer token that is stored in localstorage (bad idea)/cookie of the browser.
This is what you are trying to do:Call a protected API from React
This is the walk through example of how to do it: Basic Authentication Quick React Setup
Here are some example use cases with different application architecture scenarios:Application Architecture Scenarios
React's documentation is correct, secrets should not be used directly in the React project. But the problem is how to ensure only authorised users get access to protected paths. One way is to use username and password login but you said its the "easyway" and you need it to be automatic. So another way is to ensure authorisation by bearer token stored in localstorage(bad idea)/cookie of the user's browser - this creates a new problem: how to generate a bearer token to allow access. The solution is to use universal login by Auth0 (or Oauth, or OpenID, or Google Authenticator, or some other token generator that the user can possess (like a mobile app (Google Authenticator) or a hardware token)).
Sensitive data should not be on the frontend, you can use env for information like API_URL but not for tokens and passwords
Here is the possible ways to get sensitive data in the frontend
Http call to the backend where secrets are hashed
Http call to an external secret management tool like HashiCorp Vault
Use of httpOnly cookie that they couldn't be read from the frontend
If you are scripting user and password, you should try a tool like jscrambler to secure your build js files
When API calls are made from the frontend (i.e. your react app) anyone using your app can see the request that was made (with tokens, keys, etc.). You should always secret vars to an .env file and keep this file only on your local machine.The best way to handle this, in my opinion, is to use a framework like next or remix that allow you to create functions/api routes that run on the server. This way your frontend makes a request (no sensitive info there) to your server that has access to your keys/tokens. The real call to an external API will be made from the server (so users won't have access to any sensitive data). Not sure if this is something you're interested in but I feel like it's the best way to deal with API calls.
I suggest creating a ".env" to store all your secret keys.
In your ".env" file you can make this one
Eg:
REACT_APP_API_KEY=5155645fdsffsdfs
And in your component, you'll call it
Eg :
const apiKey = process.env.REACT_APP_API_KEY

Testing UI with locust

I have been able to load test the backend APIs of my web application using locust in my CIT environment.
Since the CIT is a protected environment, I had to manually login with my user in CIT environment via browser and copy the required request headers and use them in code to send successful requests.
My current code:
import time
from locust import HttpUser, task, between
class TestUser(HttpUser):
wait_time = between(0.1, 0.2)
#task
def client_dashboard(self):
print('load testing "Client Dashboard" screen')
client_req_headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJMT3Etc0JueEtvYkZHbWNzaU9FT0pzV3VHSjB5MEJreDlISU5xUjZQbUEwIn0.eyJleHAiOjE2MDiJ9.xNIZqrZjvVkauLUVHv1dSb9vqOHtb1-kfBG94hZqGqhXWaK06IfYuYsFJlpmSa4mcauW',
'realm': 'Client1'
}
self.client.get("/order-service/orders/summary/12", headers=client_req_headers)
self.client.get("/order-service/clients/12/", headers=client_req_headers)
def on_start(self):
print('In on_start method')
def on_stop(self):
print('In on stop method')
I am new to locust and so far I have been able to identify that with locust I can send many concurrent requests by defining tasks in my User classes. Whatever behavior I define in my tasks will be load tested.
I wanted to know if I can also check the UI flow using locust. i.e. Open the login page via code, Enter the credentials and submit. Then directed to the dashboard page on successful login and navigate the different links (Our frontend is an SPA (single page application) built using Quasar)
Does locust provide this functionality?
Would I have to include another python library for this case like selenium etc. ?
What would be the recommended way to achieve such behavior?
Locust doesn't have built-in support for anything like that. It's primarily designed for just API and endpoint testing. But it's flexible enough to run any code in an orchestrated and distributed manner so it is possible. There are community modules that should be able to get you what you want. I haven't tried it but you could look at this:
https://github.com/nickboucart/realbrowserlocusts

Google Directory API always return 403 when using OAuth2.0 even after user consent

I am working on a web app and struggling with Google Directory API.
The app is trying to get the list of the google groups user belongs to with the simple code as following:
from apiclient import discovery
from google.appengine.api import users
from oauth2client.appengine import OAuth2DecoratorFromClientSecrets
def decorator():
....(some scopes including admin.directory.group)
return decorator
class MainHandler(webapp2.RequestHandler):
#decorator.oauth_required
def get(self):
me = users.get_current_user()
http = oauth_decorator.http()
service = discovery.build('admin', 'directory_v1', http=http)
grouplist = service.groups().list(userKey=me).execute()
....
This results in 403 Not Authorized to access this resource while Admin SDK is enabled. There are a lot of questions report similar problems but the major difference is I am trying to use OAuth2.0 instead of using service account, which means the user need explicitly consent and grant the authority I ask for.
So my guessing is for some reason, the request is not with the proper user authorization code, but I have no idea how I can prove my suspicion and how I can make it work. Any suggestions? Much thanks in advance!
I contacted Google and it turns out to be that I need to be domain administrator in order to use ANY Admin APIs listed.
Not quite feasible in my case, so I am trying to find ways around.
Since there is a scope defined for each API, the admin will need to grant a consent for it at the time of token generation. If you are using OAuth2.0, once you generate a refresh token, you are good to go.

Cloud Endpoints HTTP Cookies

I am implementing Cloud Endpoints with a Python app that uses custom authentication (GAE Sessions) instead of Google Accounts. I need to authenticate the requests coming from the Javascript client, so I would like to have access to the cookie information.
Reading this other question leads me to believe that it is possible, but perhaps not documented. I'm not familiar with the Java side of App Engine, so I'm not quite sure how to translate that snippet into Python. Here is an example of one of my methods:
class EndpointsAPI(remote.Service):
#endpoints.method(Query_In, Donations_Out, path='get/donations',
http_method='GET', name='get.donations')
def get_donations(self, req):
#Authenticate request via cookie
where Query_In and Donations_Out are both ProtoRPC messages (messages.Message). The parameter req in the function is just an instance of Query_In and I didn't find any properties related to HTTP data, however I could be wrong.
First, I would encourage you to try to use OAuth 2.0 from your client as is done in the Tic Tac Toe sample.
Cookies are sent to the server in the Cookie Header and these values are typically set in the WSGI environment with the keys 'HTTP_...' where ... corresponds to the header name:
http = {key: value for key, value in os.environ.iteritems()
if key.lower().startswith('http')}
For cookies, os.getenv('HTTP_COOKIE') will give you the header value you seek. Unfortunately, this doesn't get passed along through Google's API Infrastructure by default.
UPDATE: This has been enabled for Python applications as of version 1.8.0. To send cookies through, specify the following:
from google.appengine.ext.endpoints import api_config
AUTH_CONFIG = api_config.ApiAuth(allow_cookie_auth=True)
#endpoints.api(name='myapi', version='v1', auth=AUTH_CONFIG, ...)
class MyApi(remote.service):
...
This is a (not necessarily comprehensive list) of headers that make it through:
HTTP_AUTHORIZATION
HTTP_REFERER
HTTP_X_APPENGINE_COUNTRY
HTTP_X_APPENGINE_CITYLATLONG
HTTP_ORIGIN
HTTP_ACCEPT_CHARSET
HTTP_ORIGINALMETHOD
HTTP_X_APPENGINE_REGION
HTTP_X_ORIGIN
HTTP_X_REFERER
HTTP_X_JAVASCRIPT_USER_AGENT
HTTP_METHOD
HTTP_HOST
HTTP_CONTENT_TYPE
HTTP_CONTENT_LENGTH
HTTP_X_APPENGINE_PEER
HTTP_ACCEPT
HTTP_USER_AGENT
HTTP_X_APPENGINE_CITY
HTTP_X_CLIENTDETAILS
HTTP_ACCEPT_LANGUAGE
For the Java people who land here. You need to add the following annotation in order to use cookies in endpoints:
#Api(auth = #ApiAuth(allowCookieAuth = AnnotationBoolean.TRUE))
source
(Without that it will work on the local dev server but not on the real GAE instance.)

Custom SignIn & SignUp on RESTlet + GAE/J?

I am currently working on a small project using RESTlet on Google App Engine/Java.
I was searching.. searching.. and couldn't find the exact or understandable solutions for my doubts.
My question is that How am I suppose to implement my own SignIn & SignUp module without using google's UserService or Spring Security??
Is there any actual sample code available??
I mean SignUp part is just a simple JDO insert & select module. let's just say I've done it.
How am I supposed to handle each user's request session and authentication??
I am thinking about using HTTPS on every request.
Any suggestions or help would be really appreciated!
Thanks in advance.
In Restlet, you have security support on both client and server sides. On client side, you can specify security hints using the ChallengeResponse entity. This feature is open and you can specify the authentication type you want. In the following code, I use an http basic authentication based on username / password:
ClientResource cr = new ClientResource(uri);
ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
ChallengeResponse authentication = new ChallengeResponse(
scheme, "username", "password");
cr.setChallengeResponse(authentication);
Restlet will automatically build necessary headers in the corresponding request. You can note that Restlet supports a wide range of authentication types through its extensions. I know that some work is done at the moment to support OAuth v2 (see http://wiki.restlet.org/developers/172-restlet/257-restlet/310-restlet.html).
On the server side, you need to secure accesses at routing level using the ChallengeAuthenticator entity, as described below. This can be done within your Restlet application:
public Restlet createInboundRoot() {
Router router = new Router(getContext());
ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
ChallengeScheme.HTTP_BASIC, "realm");
guard.setVerifier(verifier);
guard.setEnroler(enroler);
guard.setNext(router);
return guard;
}
Like for client side, this support is generic and is based on two interfaces that need to be specified on the guard:
The verifier one to check if authentication is successful
The enroler one to fill roles for the authenticated user
You can notice that same security technologies need to be use on both sides...
If you want to manage authentication session for user, you need to implement it by yourself using cookies.
When authentication successes on server side, you can return a cookie containing a security token that allows you checking the user from your database (for example). Some code like below can implement that:
CookieSetting cookie = new CookieSetting(0,
SECURITY_COOKIE_NAME, securityToken);
Series<CookieSetting> cookieSettings = response.getCookieSettings();
cookieSettings.clear();
cookieSettings.add(cookie);
You can extend for example the SecretVerifier class of Restlet to add a test on security data received and add this code when receiving the security cookie.
On client side, you need to add hints for authentication the first time and then re send the security cookie following times, as described below:
ClientResource clientResource = (...)
(...)
Cookie securityCookie = new Cookie(0,
SECURITY_COOKIE_NAME, securityToken);
clientResource.getRequest().getCookies().clear();
clientResource.getRequest().getCookies().add(securityCookie);
Hope it will help you!
Thierry
If you are interested in re-using social accounts, you need to integrate with each one like facebook oauth
And/Or use the app engine authentication via OpenID
Both ways define an API to authenticate a client, you can use the UserService or manage your own state via cookies.

Resources