I am trying to invoke GCP functions through my angular app hosted on App Engine. I cannot seem to find any straightforward answer given my users are not signed up through GCP but through Google Workspace. So in short the app I am building is only for internal users. As of right now I am able to log in fine using Google Authentication, the problem is that after I log in, the cloud function is rejecting my request. I have included all the steps that I've taken along with the error I am receiving from the cloud function.
So heres what I've done so far.
I implemented the login button inside of my Angular app using
angularx-social-login.
I then obtained an OAuth 2.0 Client ID from
the GCP project in which the functions are hosted (as this is the
same project anyway).
After this I registered the OAuth consent screen and set it to internal as I don't
want anyone but my internal workspace users to be able to access this
I then went to users identity platform and registered the same OAuth
2.0 client ID that I spoke of in step 2.
I then set up the GCP function to allow allAuthenticatedUsers (I've tried many other
roles but I would accept if I could just get allAuthenticatedUsers to work for now)
Finally back in my angular app I passed into the function call
headers the idToken that I get each time a user logs in using the
Google Login Popup
My code looks like:
DashboardComponent.ts
import {SocialAuthService} from 'angularx-social-login';
...
this.authService.authState.subscribe((user) => {
this.myService.callFunction(user.idToken).subscribe((userRes) => {
...
}
...
FirebaseFunctionService.ts
callFunction(authToken): Observable<any> {
const headers= new HttpHeaders()
.set('content-type', 'application/json')
.set('Access-Control-Allow-Origin', '*')
.set('Authorization', `Bearer ${authToken}`);
return this.http.get('https://my-cloud-function-url/my-function', { headers: headers
});
}
And the response that I get when I call this function is:
error: ProgressEvent {isTrusted: true, lengthComputable: false,
loaded: 0, total: 0, type: 'error', …} headers: HttpHeaders
{normalizedNames: Map(0), lazyUpdate: null, headers: Map(0)} message:
"Http failure response for
https://myFunction.cloudfunctions.net/myFunction: 0 Unknown Error"
name: "HttpErrorResponse" ok: false status: 0 statusText: "Unknown
Error" url: "https://myFunction.cloudfunctions.net/myFunction"
[[Prototype]]: HttpResponseBase
Does anyone know why this might be happening? Any help would be greatly appreciated as I am at my wits end. Thanks in advance :)
Status code 0 in the error message indicates a CORS failure. You can go through this GitHub issue comment, where the stackoverflow thread points to a number of reasons for this error.
Also you need to write this line of code in your initialisations :
const cors = require('cors')({origin: true}) and check out Google’s documentation on how to handle CORS requests. Also you have to provide proper permissions - one of the important ones being giving Cloud Functions invoker role to your cloud functions.
Joe, (author of our question) agreed that it was a CORS error but he solved it by giving allUsers permission (making the function public) and verifying the user in the function itself and the CORS disappeared.
Now the reason behind this :
I think there was some issue with Joe’s authentication mechanism and hence functions were not authenticated. HTTP functions require authentication by default. And as it did not have it, as per documentation the workaround was to make Joe’s function public by setting the --allow-unauthenticated flag, or use the Console to grant the Cloud Functions Invoker role to allUsers. Then handle CORS and authentication in the function code (which he was doing as he mentioned).
So when Joe made the function public by granting allUsers and CORS was handled in code, it started working and the CORS errors disappeared.
I registered dataflow with command : gcloud deployment-manager type-providers create dataflow --descriptor-url='https://dataflow.googleapis.com/$discovery/rest?version=v1b3'
When i run this script
- name: "my-topic-to-avro"
type: 'project_id/dataflow:dataflow.projects.locations.templates.launch'
properties:
projectId: project_id
gcsPath: "gs://test-create-123"
jobName: "my-topic-to-avro"
location: "europe-west1"
parameters:
inputTopic: "projects/project_id/topics/test"
outputDirectory: "gs://test-create-123/"
avroTempDirectory: "gs://test-create-123/"
In output i have this :
ERROR: (gcloud.beta.deployment-manager.deployments.update) Error in Operation [operation-1598980583c2a0ec69]: errors:
- code: RESOURCE_ERROR
location: /deployments/quick-deployment/resources/my-topic-to-avro
message: '{"ResourceType":"project_id/dataflow:dataflow.projects.locations.templates.launch","ResourceErrorCode":"401","ResourceErrorMessage":{"code":401,"message":"Request
is missing required authentication credential. Expected OAuth 2 access token,
login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","status":"UNAUTHENTICATED","statusMessage":"Unauthorized","requestPath":"https://dataflow.googleapis.com/v1b3/projects/project_id/locations/europe-west1/templates:launch","httpMethod":"POST"}}'
I can have my token run command : gcloud auth print-access-token, but i don't know where insert my value and the schema for my yaml to insert all value to create dataflow.
Any help appreciated.
The "401 - Request is missing required authentication credential" error message that is triggered when doing a POST request to the Dataflow API is due to a missing credential. The following public reference explains in detail how to use OAuth 2.0 to access Google APIs. Please read it carefully and make sure to follow the steps as mentioned to avoid any errors.
Another place to check this is double check that the Dataflow API is enabled and try setting "GOOGLE_APPLICATION_CREDENTIALS" to point to the JSON of the service account you are using.
I found this Authentication documentation where is mentioned that you can use the Authorization header to supply an access token from the project's service account, you can also try with this method but is important t o clarify that is an example for GKE cluster.
I noticed this question was addressed in this post.
I am using AWS Amplify in my react app to call my API hosted in API Gateway with AWS_IAM authorization. When I set authorization to NONE, everything works fine in my react app.
However, when I set authorization to AWS_IAM and execute my API using API.get() from Amplify like the code below:
const notes = await API.get('notes', '/notes', init);
I get an error message like:
{
"message": "Missing Authentication Token",
"err": "missing auth"
}
So I tried to use aws-api-gateway-cli-test to test my API gateway. Through the script, I was able to get a valid credential, get authenticated and correct response. I have also tried the POSTMAN with my admin credentials and it worked as well.
After doing some research, I saw people referring this to CORS issue. I have double checked my API gateway settings and confirmed that I have enabled CORS. The same issue persists.
Through the debugging feature of aws-amplify, I was able to see the signing process in my Chrome inspector. The signing process was performed properly with some accessKey and secretKey. I pulled those keys out of the inspector into my POSTMAN and tried to get.
These credentials are not valid and I received the following error message:
{
"message": "The security token included in the request is invalid.",
"err:": "default"
}
Update: I forgot to copy session token into POSTMAN. Now with all credentials generated by my app I am able to get correct result from my API in POSTMAN. Just not in my app.
At this point, it is pretty obvious to me that it is an auth problem. However, I have been using aws-amplify for sign-in and get process. Pretty sure the signing process is done by amplifying behind the scenes.
I have spent 3 days on this problem and basically tried everything... Any ideas on why it doesn't work?
P.S. A lot of people have suggested that typos in the invoke URL could lead to this issue. I have double checked and there is no typo. Below is my amplify configure code:
Amplify.configure({
Auth: {
mandatorySignIn: true,
region: config.cognito.REGION,
userPoolId: config.cognito.USER_POOL_ID,
identityPoolId: config.cognito.IDENTITY_POOL_ID,
userPoolWebClientId: config.cognito.APP_CLIENT_ID
},
Storage: {
region: config.s3.REGION,
bucket: config.s3.BUCKET,
identityPoolId: config.cognito.IDENTITY_POOL_ID
},
API: {
endpoints: [
{
name: "notes",
endpoint: config.apiGateway.URL,
region: config.apiGateway.REGION
}
]
}
});
Just resolved my problem - I have had Authorization settings for OPTIONS method to be AWS_IAM under Resources in API Gateway. However when my browser send a request it will send one to OPTIONS first to check for certain headers without the credentials in this request.
Since I set OPTIONS with IAM authorization, the OPTIONS method then checked against IAM with this request without my credentials. This is why I received "Missing Authentication Token".
The problem was this in my case:
import { Auth } from 'aws-amplify';
import { API } from 'aws-amplify';
I know, I now it's banal. This why I should't code when I am exausted.
I tried to connect my Alexa AWS Lambda function (node.js 6.10) with Azure Activ Directory to my Azure-Cloud-API. After reading the documentation from amazon and many tutorials I have now a working Account Linking. That means, I can link the Account of the Skill inside the Alexa-App on my smartphone.
AccountLinking for my Custom Skill:
{Data from my azure portal}
Authorization Grant Type: Auth Code Grant
Authorization URI: {OAUTH 2.0 AUTHORIZATION ENDPOINT}
Access Token URI: {OAUTH 2.0 TOKEN ENDPOINT}
Client ID: b9c6[...]bc60 {Application ID}
Client Secret: {Client Secret}
Client Authentication Scheme: Credentials in request body
scope: openid
domain: empty
redirect urls: --> In Azure portal as ALLOWED TOKEN AUDIENCES and Reply URLs defined
In my aws lambda function I get the event request from alexa like the documentation says with properties for version, session, context, request...
My understanding of the documentation is, that the token I need for the Azure-Cloud-API-Request should be here: session.user.accessToken
But this token doesn't look like the one I need and after my test runs I get always "Unauthorized" back.
The Token looks something like this and is 1252 characters long:
AQABAAAAAADX8GCi6Js6SK82TsD2Pb7rqGN56iHT_YSxlSr1RAdXucGs0S3ykOaw0XZ1WnjJotqZAn9BH7agRbP0VQv2rnJuRw_aJil7 [...] JIEO2Ap4wuG-tTwiSmZBfbLhyYtwQmxLAkqiLApqFmBYcyu-dnzlVV4liDGyTQ7gAXufd3zt7QGmi3UfP1aL9f5NBeXbmxnU6FHRzF10QZa19pTQgNTtIK8oIAA
If I configure postman and send a request to the azure activ directory I get a accessToken like this (1168 characters long):
eyJ0eXAiOiJKV1QiLCJhbGc [...] Ezbk5aY2VEYyJ9.eyJhdWQiOiJodHRwczovL21ldGVvcmEtYXBwLmF [...] kY5MWVUUXdBQSIsInZlciI6IjEuMCJ9.KJco47-FdJ_eeqv38LL [...] YK_4JqCRDw
This one looks like a jwt-token and if I copy this token directly in my aws lambda function and use this one for the Azure-Cloud-API-Request it works (until the token expires).
Now I'm not sure if there is a problem in my configuration of the account linking? Or do I have to do something with the token from alexa to get the real one? Or is the real token somewhere else and I have to fetch it there?
Thanks a lot for your help!
Amazon Documentation "Alexa Skills Kit":
https://developer.amazon.com/docs/custom-skills/link-an-alexa-user-with-a-user-in-your-system.html
EDIT (Solution) 11.06.2018
Authorization Grant Type: Auth Code Grant
Authorization URI: {OAUTH 2.0 AUTHORIZATION ENDPOINT} + ?resource= + {Application ID}
Access Token URI: {OAUTH 2.0 TOKEN ENDPOINT}
Client ID: b9c6[...]bc60 {Application ID}
Client Secret: {Client Secret} App>Settings>Keys new Key with expiration date = 2 years
Client Authentication Scheme: Credentials in request body
scope: empty
domain: empty
redirect urls: --> In Azure portal as ALLOWED TOKEN AUDIENCES and Reply URLs defined
It sounds like you haven't completed the account linking sequence for your skill. After setting the account linking configuration you need to open the Alexa app (on your phone or https://alexa.amazon.com) and go to your new skill and link your account. Once that is successful you will get a token in request.Session.User.AccessToken.
The blog post: https://blogs.msdn.microsoft.com/premier_developer/2017/12/09/amazon-alexa-skills-authenticated-by-azure-active-directory-and-backed-by-asp-net-core-2-0-web-api-hosted-on-azure/ needs to be updated with the following:
You can ignore the sections about the "front end" app registration.
In Alexa account linking section update URLs to use login.microsoftonline.com instead of login.windows.net
ClientId to be the Application Id of the "back end" app registration
The ?resource= has to be set and has to be the same as the audience parameter for the JWT bearer options. This is ClientId if you use the .Net Core 2.0 template in Visual Studio.
The client secret (key) that is used can not be one that "Never Expires". Use a 1 or 2 year duration.
In addition to Nate's answer and following the addition of ?resource= to the Authorisation URI, I had to give the API permission Azure Active Directory Graph > User.Read on the App Registration and Grant Admin Consent to it.
Without this permission, the account linking would throw an error. If you have similar issues, try your OAuth values with Postman and check the Postman Console for error messages
I am trying to call a Lambda Function through AWS API Gateway.
When I mention Authentication type NONE it works fine but API become public and anyone with url can access my API.
To make API call secure, I am using Authentication type AWS_IAM and
also attached AmazonAPIGatewayInvokeFullAccess policy to my user but getting this error:
{ message: "Missing Authentication Token"}
I don't know what I am missing here.
I've lost some time for a silly reason:
When you create a stage, the link displayed does not contain the resource part of the URL:
API URL:
https://1111.execute-api.us-east-1.amazonaws.com/dev
API + RESOURCE URL
https://1111.execute-api.us-east-1.amazonaws.com/dev/get-list
The /get-list was missing
And of course, you need to check that the method configuration looks like this:
I think you are directly trying to access API link, this won't work because API is secured using IAM role and you must provide AWS authentication i.e Access key and Secret key.
Use the Postman Chrome extension to test your API:
http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-use-postman-to-call-api.html
I just had the same issue and it seems it also shows this message if the resource cannot be found.
In my case I had updated the API, but forgotten to redeploy. The issue was resolved after deploying the updated API to my stage.
Make sure you are clicking on the specific Resource first in the Stages tree, as that will populate a URL with the full path to the resource (rather than just the root path):
For other causes, see http://www.awslessons.com/2017/aws-api-gateway-missing-authentication-token/
Looks like (as of April 2019) AWS API Gateway throws this exception for a variety of reasons - mostly when you are hitting an endpoint that API Gateway is not able to reach, either because it is not deployed, or also in cases where that particular HTTP method is not supported.
I wish the gateway sends more appropriate error codes like HTTP 405 Method not supported or HTTP 404 not found, instead of a generic HTTP 403 Forbidden.
Found this in the docs:
If the AWS_IAM authorization were used, you would sign the request using the Signature Version 4 protocols.
Signing request with Signature Version 4
You can also generate an SDK for your API.
How to generate an SDK for an API in API Gateway
Once you've generated the SDK for the platform of your choice, step 6 mentions that if you're using AWS credentials, the request to the API will be signed:
To initialize the API Gateway-generated SDK with AWS credentials, use code similar to the following. If you use AWS credentials, all requests to the API will be signed. This means you must set the appropriate CORS Accept headers for each request:
var apigClient = apigClientFactory.newClient({
accessKey: 'ACCESS_KEY',
secretKey: 'SECRET_KEY',
});
I try all the above, if you did all steps in the above answers, and you not solve the problem, then:
on the left menu, hit the "Resources"
in the right to "Resources", hit the api method that you want to test, like "POST/GET etc)
hit the "ACTION" list (it's above to the API method in step 2
select "DEPLOY API" (please do it, even you already deploy yours api)
in "deployment stage" select "prod" or what ever you write in yours previous deploy (it will override yours previous deploy
hit deploy
I thing that because of, when I create the "METHOD REQUEST" (see step 2 how to go to this menu) , in "Authorization" I select "AWS_IAM"
after testing api, in aws test option, I try it in "postman"
then I understand the in "METHOD REQUEST" , in "Authorization", I should select "none"
I change it to none, but I thing the AWS, need to deploy it again, as I explain
Make sure you create Resource and then create method inside it. That was the issue for me. Thanks
In my case I missed adding '/' forward slash at the end of api.
Such a silly mistake.
https://le9dq5l9.execute-api.eu-west-1.amazonaws.com/v1/putdoctorinfo/
If you enable AWS_IAM authentication you must sign your request with AWS credentials using AWS Signature Version 4.
Note: signing into the AWS console does not automatically sign your browser's requests to your API.
sometimes this message shown when you are calling a wrong api
check your api endpoint
In my case it was quite a stupid thing.
I've get used that new entities are created using POST and it was failing with "Missing Authentication Token". I've missed that for some reason it was defined as PUT which is working fine.
This error mostly come when you call wrong api end point.
Check your api end point that you are calling and verify this on api gateway.
If you are using an API with endpoint of type PRIVATE, be sure of:
You are invoking the API from within your AWS account (example: from an EC2 instance created in your account)
Put necessary credential (access and secret keys) in the EC2 instance in route ~/.aws/credentials (this route is for linux instances) If IAM user use MFA aws_session_token value will be required too.
Use vpce (vpc endpoint) based URL. Example: curl https://vpce-0c0471b7test-jkznizi5.execute-api.us-east-1.vpce.amazonaws.com/dev/api/v1/status
Your EC2 instance have a security group than allow outbound traffic to another security group owned by the vpce like:
Your vpce security group allow inbound traffic from another security group (previous sg from ec2 instance) owned by the EC2 instance like:
See: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html
I had the same problem which I solved the following way:
GET Method test
https://54wtstq8d2.execute-api.ap-southeast-2.amazonaws.com/dev/echo/hello
Authorization tab ->
• select type(AWS signature)
• Add AccessKey and SecretKey
You must be using Invoke Url to trigger Lambda Function from your browser or POSTMAN... Instead, use the API end point which will be listed in:
select yourLambdaFuntion >> Configuration >> Triggers.
There you can see API end point.
For the record, if you wouldn't be using credentials, this error also shows when you are setting the request validator in your POST/PUT method to "validate body, query string parameters and HEADERS", or the other option "validate query string parameters and HEADERS"....in that case it will look for the credentials on the header and reject the request. To sum it up, if you don't intend to send credentials and want to keep it open you should not set that option in request validator(set it to either NONE or to validate body)
I had the same issue, and fixed it by removing the /dev/ and just put: https://1111.execute-api.us-east-1.amazonaws.com/get-list
I had same issue today because I was using GET instead of POST. Fixed the issues by changing method to POST in postman.
First of all, check whether the API you created in the lamda function is registered with your AWS project or not. For that, go to the API gateway in your AWS console. If it is not registered, register it. This is the main cause of this issue.
You can even see in your aws.export.js file, that there are paths corresponding to your API ['/items'].
Your API must be present there, otherwise it will not append the security token to requests. Just register it in your project cloud-logic in your console for this.
If it's there, then use the above mentioned solution
http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-use-postman-to-call-api.html
To contribute:
I had a similar error because my return response did not contain the 'body' like this:
return {
'statusCode': 200,
'body': "must contain the body tag if you replace it won't work"
}
If you set up an IAM role for your server that has the AmazonAPIGatewayInvokeFullAccess permission, you still need to pass headers on each request. You can do this in python with the aws-requests-auth library like so:
import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
auth = BotoAWSRequestsAuth(
aws_host="API_ID.execute-api.us-east-1.amazonaws.com",
aws_region="us-east-1",
aws_service="execute-api"
)
response = requests.get("https://API_ID.execute-api.us-east-1.amazonaws.com/STAGE/RESOURCE", auth=auth)
Well for anyone still having the problem and I really feel very dumb after realizing this, but I passed in the url of /items the default one while adding API. But I kept calling the endpoint with /api. Special thanks to Carlos Alberto Schneider, as I realized my problem after reading your post.
According to my experience, please check the following steps:
On API gateway side, make sure you add the correct path and publish the resource at the stage you want. For some url pattern like path parameter(/user/{user_id}) need more attention to have a check.
Make sure you configure the correct options method for this resource, because sometimes it is the CORS that cause this problem.
On Lambda side, make sure you specify the correct handler name as the entrypoint.
Please always check cloudwatch logs of your lambda that can help u identify the problems on your lambda side.
In my case I was trying to do an UPDATE type request but in my AWS SAM template I had a PATCH type request:
Resources:
LambdaFunction:
Type: AWS::Serverless::Function # More info about Function Resource:
# https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: src/
Handler: app.lambda_handler
Runtime: python3.8
MemorySize: 128
Events:
UpdateItem:
Type: Api
Properties:
Path: /my-endpoint
Method: patch
Things to check:
1. In resources, check for Authorization and API Key if these are required.
2. Redeploy the API, new changes might not reflected.
3. Get the url from stages, directly by clicking on the actions like GET, POST, These will contain the full path urls.
I had the same issue even if my access was regional and not private, no authorization on my method neither API. It's turned out that I was calling the root endpoint "https://azerty.execute-api.eu-west-3.amazonaws.com/dev/", which in local return me a json but raised an error. Be sure to call a proper endpoint, such as "https://azerty.execute-api.eu-west-3.amazonaws.com/dev/hello"