inspite of mentioning allowed_client_ids in api declaration all web clients are able to access api - google-app-engine

import endpoints
from protorpc import messages #for encapsulating data for sending
from protorpc import message_types
WEB_CLIENT_ID = '644515464936-552tgvthbmnhopg6qe71e99rrfbjatj7.apps.googleusercontent.com'
class HelloMessage(messages.Message):
msg = messages.StringField(1)
#endpoints.api(name='myapiversion1',
version='v1',
allowed_client_ids=[WEB_CLIENT_ID],
audiences=[WEB_CLIENT_ID],
scopes=[endpoints.EMAIL_SCOPE],
auth_level=AUTH_LEVEL_REQUIRED,
hostname='maulikversion1.appspot.com')
api url : https://maulikversion1.appspot.com/_ah/api/maulikversion1/v1/say_hello
I tried accesing it from www.hurl.it a web tool for testing rest api, and it was able to access the api.
Q1
what error it should give instead of allowing to access my custom api?
unfortunately it is allowing any web client to access api.
Q2.
AUTH_LEVEL_REQUIRED is not defined - internal server error

It is now restricting other web clients to access the api
I guess the client id generation took time to reflect at production-environment

Related

How to avoid CORS error for a React - GraphQL application

I am currently trying to use camunda platform and in this concept I am building a react application to make a call to a graphQL api and perform some actions. So far, I have used the api with postman and does the job I want to, The graphql mutation is the following:
mutation claimTask ($taskId: String!, $assignee: String) {
claimTask (taskId: $taskId, assignee: $assignee) {
id
name
taskDefinitionId
processName
creationTime
completionTime
assignee
variables {
id
name
value
previewValue
isValueTruncated
}
taskState
sortValues
isFirst
formKey
processDefinitionId
candidateGroups
}
}
And the endpoint is
http://{my_ip}:8082/graphql
which is set in a personal vm server. What I am trying to do now, is make the same request through the react app (apollo client). So far, I am getting a cors policy error:
Access to fetch at 'http://{my_ip}:8082/graphql' from origin 'http://localhost:3000' has been blocked by CORS policy
I understand that I have to configure somehow the uri that can be accepted by the server. My question is, since I am using an existing api should I do this from the express server (apollo server) configuration? Because so far every solution I found talks about implementing the api from the scratch, including defining the schemas.
I have concluded, that I should use the express server to create a kind of proxy so that the react app will hit the api through there but I cannot figure out how exactly is this implemented.
I know that this is a vague question, but any suggestion could be very useful.
Thank you!!
It is a best practice to not hit the GraphQL API directly, but to create your own facade, which exposes the functionality your front-end needs, possibly in a more use case specific way. This means connectivity only needs to be allowed server-to-server between the back-ends. It is more secure as you don't need to open the API to the public and it also solves the cross-domain challenge you have. Your facade will be exposed under your domain.
Here is a example NestJS client "Generating the Tasklist service":
https://docs.camunda.io/docs/apis-clients/tasklist-api/tasklist-api-tutorial/#generating-the-tasklist-service
On your express backend you would do something similar.
(This example uses a Java back-end with react, but I am guess you want JS: https://github.com/camunda-community-hub/camunda-8-lowcode-ui-template/blob/main/src/main/java/org/example/camunda/process/solution/facade/TaskController.java .)

Sveltekit: Sharing service objects (e.g. configured http client) across pages

I am moving my app from Svelte SPA (original) to Sveltekit multi page app (new).
In the original app, I configure a http client up top and put it context using:
setContext(HTTP_CLIENT, httpClient)
Now the entire app can get that http client using
const httpClient = getContext(HTTP_CLIENT)
I do this because my app can be started with debug parameters than turn on http request logging.
I'm not clear how to do similar in Sveltekit, because it seems that pages do not share a context.
I tried sticking the http client in the session like this:
import { session } from "$app/stores";
$session.httpClient = httpClient
and I got:
Error: Failed to serialize session data: Cannot stringify arbitrary non-POJOs
So $session is meant to be serialized, ok. Does that mean that I need to put whatever debug parameters a user supplied in $session, and each page needs to freshly instantiate its own http client? Or is there some other idiomatic sveltekit way of doing this?
PS I know sveltekit has its own fetch so you might want to say "don't use your own http client", but my app uses many different service objects (graphql client for example) that can be configured in debug (and other) modes, so please don't zero in on the fact that my example is a http client.
One way around this could be to send down the configuration in the top __layout file, create the http client there and store in a store. Since stores are shared across all pages the client can then freely use this store.

401 Unauthorized calling my Azure Rest API

I have a Rest API using controllers, etc, hosted in Azure that has been working for some time. I want to secure the various methods. I added the API App (.NET core) to the App Registrations, and also added the javascript client app to App Registrations. I believe I'm initializing everything in startup.cs in the REST Api OK. I added [Authorize] to one of the methods. I used a simple javascript example which calls myMSALObj.loginPopup, and gets back a token which I then add to the Authorization header and make a fetch call. When I call, I see HTTP Error 401.0 - Unauthorized in the log stream for my App Service.
Any ideas how I can troubleshoot this to get more specifics about what is wrong?
Also, a related question: in App Registrations, Api Permissions, how does one correlate the API permission name with the method in the controller?
Add this in front of the method in the controller
[AuthorizeForScopes(Scopes = new[] { "My.Scope" })]

No way to search Yahoo Mail programmatically with Java?

I have been working on a Java app that connects to Yahoo mail to enable a user to search through their Yahoo email.
Recently, Yahoo suddenly (with only 5 weeks notice) discontinued Yahoo Mail API, which we were using and worked great. Then we re-engineered and switched to YQL. Unfortunately, for unknown reasons, this too has stopped working as of this week. The endpoint keeps returning an error. Even when YQL did work, it was occasional and sporadic. Even the Yahoo YQL console is returning errors. We have tried using JavaMAIL IMAP access to search for messages. We can connect to the IMAP server, but the JavaMAIL Search terms are not supported. I keep getting the error "SEARCH Server error - Please try again later". The same code works just fine for other IMAP services (like Aol mail).
So basically, with Yahoo Mail API gone, YQL not working, and IMAP not supporting searching, there is no programmatic way of searching Yahoo mail right now? Yahoo keeps telling us that the Yahoo API for IMAP access is the way ahead (see here https://developer.yahoo.com/mail/). But this is not live yet and there is no functioning documentation. Sending an email to imap-service#yahoo-inc.com was useless as no one responds to that anyway. They should learn a thing or two from Facebook on how to manage changes and maintain developer relations.
Does anyone have an alternative means to programatically search Yahoo Mail for emails with Java?
Thanks.
I managed to get IMAP access working with Yahoo through OAuth 2.0, but this code is in Python:
Follow the directions here to refresh the user's token:
https://developer.yahoo.com/oauth2/guide/index.html#refresh-token-label
(you can use the refresh_token that you received using OAuth 1.0)
Replace the email_address and access_token in the following code:
import logging
import imaplib
import datetime
import quopri
import hashlib
endpoint = 'imap.mail.yahoo.com'
email_address = 'REPLACE_THIS#yahoo.com'
access_token = 'REPLACE_THIS'
auth_string = 'user=%s\1auth=Bearer %s\1\1' % (email_address, access_token)
imap_conn = imaplib.IMAP4_SSL(endpoint) # the IMAP server we're connecting to
imap_conn.debug = 3 # for logging purposes
imap_conn.authenticate('XOAUTH2', lambda x: auth_string)
folders = imap_conn.list()
print folders
imap_conn.select('Inbox', readonly=True)
result, data = imap_conn.uid('search', None, '(FROM "Amazon.com")')
messages = data[0].split()
print 'messages:' + str(messages)
uids_to_fetch = ','.join(messages)
result, data = imap_conn.uid('fetch', uids_to_fetch, 'RFC822')
for counter, message in enumerate(data[::2]):# every other item in the list is not a message, but ")" so we skip it
# yield raw mail body, after decoding the quoted-printable encoding
print quopri.decodestring(message[1])

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.)

Resources