AppSync request from API Gateway: Valid authorization header not provided - aws-api-gateway

I have an AWS architecture like this:
An API Gateway with many endpoints. One of them is "/graphql"
The "/graphql" API Gateway endpoint points to a "/graphql" AppSync endpoint
My API Gateway uses COGNITO_USER_POOL to authentificate users. When an user makes a request to "/graphql" endpoint of API Gateway, he must to add id_token to "Authorization" header on the request. It works well.
My integration method on API Gateway gets the "Authorization" header and puts it on AppSync request using this HTTP Headers mapping:
Authorization = method.request.header.Authorization
It seems to work correctly also. Nevermind, I got this AppSync error when requesting the API Gateway endpoint:
{
"errors": [
{
"errorType": "UnauthorizedException",
"message": "Valid authorization header not provided."
}
]
}
It doesn't seems to be a token problem, because it works correctly when I request the AppSync endpoint directly (with the same Authorization header).
I observed that API Gateway adds some headers on the AppSync request, to generate a Signature. So my question is: Is there any way to do a request on AppSync from API Gateway without pass the Signature, only the id_token that user got from Cognito User Pool? I'd like to ignore IAM and use only the token (as I do when the request is done directly on AppSync from Postman).
Many thanks!

Related

CloudFront to API Gateway request returns 403: "The request signature we calculated does not match the signature you provided."

I have an API Gateway fronted by CloudFront. The API Gateway has a regional endpoint with api key disabled. An Authorization header must be sent to the regional endpoint or the endpoint returns "Missing Authentication Token" as expected.
Using the same request on the CloudFront endpoint returns the following 403 Forbidden error:
{
"message": "The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method. Consult the service
documentation for details.\n\nThe Canonical String for this request should have been\n'POST
// sensitive data here...
}
The Auth token is created from an AWS signature. The signature originates from an IAM role that allows invocation on the endpoint: "Action": "execute-api:Invoke"
Any ideas on why CloudFront isn't able to use these credentials to hit the API Gateway endpoint?
In summary,
"Postman w/ Authorization header -> API Gateway endpoint" works.
"Postman w/ Authorization header -> CloudFront -> API Gateway endpoint" returns the above 403.
UPDATE: Adding information on how I obtain the signature.
IAM Role:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:{ACCOUNT}:{ENDPOINT}",
"Effect": "Allow"
}
]
}
AccessKey, SecretKey, Session Token are obtained in CloudShell:
$ aws sts assume-role --role-arn arn:aws:iam::{ACCOUNT}:{ROLE} --role-session-name {SESSION_NAME}
These 3 keys are then used in Postman's Authorization tab. I select "AWS Signature" type and provide the AccessKey, SecretKey, and SessionToken.
From here, I can hit the API Gateway endpoint and receive 200 response. With the same request and headers, hitting the CloudFront endpoint results in the 403.
UPDATE #2: Adding information on CloudFront configuration.
The distribution behavior for the API GW origin is using the CachingOptimized policy. Its also allowing all HTTP methods.

Unable Auhorize Access to REST API end service with Azure Data Factory with Token Error status code 401 Unauthorized

I have configured our Azure Data Factory with a REST Link Service. I have obtained a valid token from the end service.
The token successfully works when using the token with POSTMAN, but the token returns Error status code 401 Unauthorized with Azure Data Factory.
As you can see with POSTMAN when I send a GET request with the Token I get data back:
However, with Azure Data Factory I get the error:
{
"errorCode": "2200",
"message": "Failure happened on 'Source' side. ErrorCode=RestCallFailedWithClientError,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=Rest call failed with client error, status code 401 Unauthorized, please check your activity settings.\nRequest URL: https://pm2.preqinsolutions.com/apiCore/api/countries.\nResponse: ,Source=Microsoft.DataTransfer.ClientLibrary,'",
"failureType": "UserError",
"target": "Copy data1",
"details": []
}
The ADF Link Service is a follows:
Can someone see something obvioius that would prevent access due 401 Unauthorized status with ADF?
I have also tried the following ADF configuration. However, I'm getting the same error:
Please try changing the authHeader name to Authorization and the value to Bearer <your API key>. I suspect from the screenshot of Postman that is what it’s doing. If that does not work then please provide a link to the documentation. This explains Bearer tokens.
You might also check the lifetime of your access token and make sure it doesn’t expire after an hour, for example.
I did a quick test against a REST API I know (Power BI REST API). The linked service looks like this and the value for the Authorization header was Bearer MY_ACCESS_TOKEN_HERE.
The dataset looks like:
The source of the Copy activity looks like:
This succeeded.
I would suggest you contact pm2.preqinsolutions.com support to see if they can provide more information on your access token / API key and have them confirm that the API isn't restricted to be accessed from only certain allowed API addresses. (ADF will not be accessing it from an on-premises IP address like your laptop.) You might also change the REST API linked service to use a self-hosted integration runtime instead of an Azure integration runtime to validate the IP address the API is called from isn't the issue.

How to authenticate curl (or Postman, or Ajax) call with Spring Cloud Gateway and Keycloak

I'm using Spring Cloud Gateway with Keycloak, and authentication works from browser.
But, there is no Authorization header with the token, but SESSION cookie instead.
I don't want to use cookies at all, but token instead.
Currently, if I post to http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token to get tokens and try to put access_token in Authorization header with Bearer it doesn't work, but returns login page.
Also if I add keycloak.js to browser page, and after successful login try to add xhttp.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
to Ajax call, it again returns login page.
So how to use Spring Cloud Gateway with Keycloak, from any client with provided valid token at all?
Here is my gateway configuration, and web app behind it with /web/ route doesn't have any security applied. Keycloak is configured with basic public client.
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
http.oauth2Login();
http.logout(logout -> logout
.logoutSuccessHandler(new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository)));
http.authorizeExchange().pathMatchers("/web/private").authenticated()
.pathMatchers("/web/**").permitAll()
.anyExchange().authenticated();
http.headers().frameOptions().mode(Mode.SAMEORIGIN);
http.csrf().disable();
return http.build();
}
If you want to make requests to Spring Gateway with access token you need to make it a resource server: https://stackoverflow.com/a/66923312/11122338

OAuth2 key/secret with github v4 graphql endpoint

How to pass the clientId and secret for github's graphql endpoint?
In documentation, they have shown it for rest endpoint but not sure how the new api (v4) will work with server to server calls.
https://developer.github.com/v3/#oauth2-keysecret
curl 'https://api.github.com/graphql?client_id=xxxx&client_secret=yyyy'
{
"message": "This endpoint requires you to be authenticated.",
"documentation_url": "https://developer.github.com/v3/#authentication"
}

Validate oAuth 2 access token in APIGEE without VerifyOAuthTokens policy

We are using Apigee as our Authorization Server (AS) and we have a few Spring Restful services deployed in IBM Bluemix public cloud which acts as our Resource server (RS).
Each of the services has an equivalent proxy service configured in Apigee. For the proxy services, we have configured the VerifyOAuthTokens policy to verify the token passed by the user and return an error if invalid token is passed
The problem is, since our RS is in the public cloud (no plans or need of moving to a dedicated or private cloud) the api endpoints are open and can be invoked by anyone who knows the url.Though the expectation is everyone should call the apis via APIGEE proxies but we cannot force that since we are in public cloud and there are no options of opening ports coming from apigee or something. We would like to take the following approach to secure the api endpoints.
Accept the Authorization header for each call
Take the token and call a validate token service in Apigee
For 2, We are not able to find an APIGEE api which can validate an access token similar to say googles
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=1/fFBGRNJru1FQd44AzqT3Zg
or Github's
GET /applications/:client_id/tokens/:access_token
Is there actually an external APIGEE service to validate a token?
If not, what would be the best way to make sure that only valid users with valid tokens can access the apis?
Thanks,
Tatha
Did you look at this post in the Apigee Community: Using third-party OAuth tokens
We did something similar to this but not using oauth tokens. We used Apigee to do a callout to a third party IDP (identity provider). The 3rd party IDP wasn't able to generate tokens but exposed a web service to authenticate the user. If the user was authenticated successfully (based on interpreting the result received back from the target endpoint webservice), then you tell Apigee that it was successful by setting the external authorization status to true (step #2 in the link).
NOTE: this has to be done inside an Assign Message Policy step PRIOR to the GenerateAccess token operation. Apigee interprets this as a successful authorization and then can generate a valid oauth token that the caller can then send along to access the protected API.