Or put another way...
I just moved my app from aaa.appspot.com to a new project (and hence new Client ID) called bbb.appspot.com. When I went to add the new Client Id to my GCE API definitions, it was already there!
So, on the one hand, it's magic :-)
On the other hand, is all of this documented anywhere? I have a slight concern about how I would go about overriding this behaviour if ever I want to manually configure the permitted client IDs.
I assume you are talking about the API annotations for GCE like this:
#ApiMethod(
name = "testAuth",
clientIds = { WEB_CLIENT_ID,
APP1_ANDROID_CLIENT_ID, APP1D_ANDROID_CLIENT_ID,
APP2_ANDROID_CLIENT_ID },
audiences = { Config.WEB_CLIENT_ID }
)
These client ID's come from the API console, where they are created based on your app's package and the hash of your app's certificate.
So, you may create a new GAE project for your new app id, and even create a new console project connected to that new GAE project, but your old console project still exists and still has client id's that are specific to your Android project but independent of your GAE project - so they still work.
Related
So I have a crud applicatio here this is the link
https://crud-application-x.herokuapp.com/getstudents
my boss was telling me this
Add one record that I can see when I visit the url.
what does it mean by adding a record on a crud app. Does it mean adding new data
I think the issue here is not related to a misunderstanding, but that you're both looking at different things. You're probably testing it at your development environment only and everything works as expected. Your boss, on the other hand, is using the app through the URL you've provided and is unable to create a new student.
The issue here is that you are not using the right address to access your API in production, so the student is never created, take a look:
The address http://localhost:3200/... will only work on your development environment. Once axios can't reach the server, adding a new student throws an Error: Network Error.
In order to fix this, you'll have to start using the right URL for each environment. The easiest way to do so, in my opinion, is through environment variables.
How to set up an environment variable
As it looks like you're using create-react-app, this resource will help you set them up as needed. As a simple example, you can create the following two files at your app root directory:
.env.development
REACT_APP_API_PATH=http://localhost:3200
.env.production
REACT_APP_API_PATH=https://crud-application-x.herokuapp.com
Now you can easily use the right URL for each environment:
axios.post(`${process.env.REACT_APP_API_PATH}/students/addStudent`)
I have a React app created with create-react-app which I have deployed to an Azure Web App. There is no back-end: the site is purely 'static'.
In the production environment, there are a number of keys to API services and other secrets that I need to keep secure, but which the client app needs to be able to read.
In React there's a mechanism for accessing environment-specific information using .env files, such as .env.production, but this is not suitable for keeping secrets, as environment variables mentioned in the code are substituted with the actual value from the .env file during the build process, and are consequently visible to anyone looking at the JavaScript in their browser.
Setting the values of the AppSettings can be done on the Azure Portal (or via suitable scripting in the CI/CD pipeline), but how can I read the AppSettings values at runtime?
A number of StackOverflow questions have been asked about this, but none of the answers address the fundamental question properly, or seem to miss the point. For example, here and here.
First off, this topic is puzzling lot of developers around the globe and it should be addressed properly in Aspnet Core. One viable option would be to set up Server-Side Rendering, but there are some of us who wouldn't benefit from it. Also, there are no proper examples for doing it for ReactJS + Redux in Aspnet Core world.
My solution is to go for a InMemoryFileProvider, see https://github.com/dazinator/Dazinator.AspNet.Extensions.FileProviders for details about the NuGet package.
To start using one, in my Configure() I'll do a:
configuredSpaFileProvider = CreateFileProvider(env);
app.UseSpaStaticFiles(new StaticFileOptions
{
FileProvider = configuredSpaFileProvider
});
My CreateFileProvider() contains an instantiation of InMemoryFileProvider-class, which can be populated with additional fake "files". Pre-existing static file on filesystem will be served with a PhysicalFileProvider.
To allow access to index.html, CSS, JavaScript and all possible static files, do what a DefaultSpaStaticFileProvider would do:
var defaultPath = "build";
if (env.IsDevelopment())
defaultPath = "public";
var absoluteRootPath = System.IO.Path.Combine(
env.ContentRootPath,
$"{ReactJSdirectory}/{defaultPath}");
var physicalFileProvider = new PhysicalFileProvider(absoluteRootPath);
Then create a provider and virtual file like this:
var inMemoryProvider = new InMemoryFileProvider();
inMemoryProvider.Directory.AddFile("/", new StringFileInfo(configJsContent, "app.config.js"));
Finally glue them together, prioritizing on the virtual files:
return new CompositeFileProvider(inMemoryProvider, physicalFileProvider);
Now that a dynamic JavaScript-file exists, it needs to be accessed on client-code. There are options for this, but I'll simply do a:
<script src="/app.config.js" async defer></script>
in my index.html. The trick is to construct a string with suitable JavaScript-parseable content setting up variables and storing them into window-object and accessing them later on a client.
Now my 12 factor application is fully compliant with third factor "Store config in the environment".
My GAE app publishes some APIs in GCP and uses the following structure:
# Replace the following lines with client IDs obtained from the APIs
# Console or Cloud Console.
WEB_CLIENT_ID = '????????????.apps.googleusercontent.com'
ALLOWED_CLIENT_IDS = [WEB_CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID]
SCOPES = [endpoints.EMAIL_SCOPE]
#endpoints.api(name=API_NAME,
version=API_VERSION,
description='An API to manage languages',
allowed_client_ids=ALLOWED_CLIENT_IDS,
scopes=SCOPES)
My doubt is if someone picks this source code from my machine or GitHub project. He or she can access the APIs using the discovered web client id.
What’s the best practice in this case?
I acknowledge that the client can expose the ID and someone have access to it. But I believe that is another matter.
There are many ways you can do this. One way is to always check in a default value for the client ID, so that when people check out your code, they have to modify it to deploy it. You can also move the client ID to its own module and not check it in at all, and make the expectation that they create their own module with their own client ID. This avoids having a modified state for a checked in file all of the time.
The client ID itself is not sufficient information to generate a valid token. The cryptography involved will prevent such a person from accessing your API.
I have an old AppEngine project which is mapped to my domain. I recently transferred this domain to Google Domains.
I created a new AppEngine project which I now want to map to my domain instead of the old project. When I attempt to do so I get the error "my-domain-name is already mapped to a project." That makes sense.
However, when I attempt to delete the mapping from my old project (console.cloud.google.com/appengine/settings/domains?project=my-old-project-name) I get an error:
"Error
Sorry, there’s a problem. If you entered information, check it and try again. Otherwise, the problem might clear up on its own, so check back later.
Tracking Number: xxxxxxx
Send feedback
"
I've tried this several times so this is for sure not clearing up on its own. (I've also tried sending feedback but not gotten any reply)
Any idea on how I can move the mapping from my old AppEngine project to the new AppEngine project?
In my case we work with other companies which would consume our APIs along with our internal javascript client. I think we need to create a web client id for javascript client. But when exposing APIs externally, is it correct to generate new web client id per company? If so do we have to update clientid each time and redeploy application?
I'm following this documentation and in their example client ids are hardcoded, if I need to give access to new 3rd party users, then I need to generate new client id for them but I'd expect to not redeploy application.
Update: I've created a feature request as per #Alex's suggestion below.
Unfortunately the docs at https://cloud.google.com/appengine/docs/python/endpoints/auth very specifically say, and I quote,
Because the allowed_client_ids must be specified at build time, you
must rebuild and redeploy your API backend after adding or changing
any client IDs in the authorized list of allowed_client_ids or
audiences
so it appears that your perfectly-reasonable use case is very explicitly not covered at this time.
I recommend you visit said page and enter a feature request via the "Write Feedback" link (around the upper right corner of the page) as well as entering a feature request on the Endpoints component of the App Engine feature tracker, https://code.google.com/p/googleappengine/issues/list?can=2&q=component=Endpoints&colspec=ID%20Type%20Component%20Status%20Stars%20Summary%20Language%20Priority%20Owner%20Log -- we monitor both, but with different processes, so trying both is best.
Sorry to be a bearer of bad news. For now, it seems the only workaround is to distribute to the other companies one of a bunch of client ids generated in advance (you can only change the valid bunch when you re-deploy, sigh) and perhaps add some extra, app-layer authorization check of your own -- exactly the kind of work endpoints should be doing on your behalf:-(.
You can use an asterisk as the client ID, that will allow any client to call it without redeploying your API backend. Not sure if this is a documented feature or not, but it works (at least) with both Python and Java.
#Api(name = "myapi",
version = "v1",
scopes = {"https://www.googleapis.com/auth/userinfo.email"},
description = "My flashy API",
clientIds = {"*"})
public class MyAPI { ... }