HttpAlbIntegration (APi Gateway) with cognito custom claims - aws-api-gateway

I'm using the HttpApi (Api Gateway) with a HttpAlbIntegration to connect to my backend. My backend requires a X-API-KEY header with a value comming from a custom claim in the JWT. So my setup is something like this:
const integration = new HttpAlbIntegration(`http-alb-integration`, albListener, {
method: HttpMethod.ANY,
vpcLink: vpcLinkStack.vpcLink,
parameterMapping: new ParameterMapping()
.appendHeader('x-api-key', MappingValue.contextVariable("authorizer.claims['custom:api_key']")
});
According to this https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html, it should work, but cdk complains about:
Invalid mapping expression specified: Validation Result: warnings : [], errors :
[Invalid mapping expression specified: $context.authorizer.claims['custom:api_key']]
All the other claims work fine: email and sub for instance. The problem only happens with custom attributes, I'm guessing because of the sintax that includes a :. I've tried different sintax alternatives, no luck. The straight question is:
how can I access custom claims from cognito authorizer in HttpApi integration?

Related

AWS API domain empty base mapping is not working

I have an api gateway v1 foo.
This api gateway has a stage bar
I am trying to setup a domain name baz.com to access this stage.
When I create a new domain name with API mapping to foo (stage and path empty), I am able to access my api with https://baz.com/bar/user/get.
However, when I try to access my api with API mapping to foo, stage to bar and path empty, querying https://baz.com/user/get doesn't work (I am getting Could not find matching action for /get and method POST). Even weirder, setting path mapping to a, I am able to query my api : https://baz.com/a/user/get.
I do not understand what I am doing wrong. I tried to set path mapping to / but I get an error : API Gateway V1 doesn't support the slash character (/) in base path mappings. To create a multi-level base path mapping, use API Gateway V2.
With path set to a :
With empty path :
I am completly lost, it turns out my lambda do get call and return a 200 :
Yet it ends up being a 404
The issue was not related to API Gateway but to the library I used, aws-lambda-routing.
There was a bug regarding the use of custom domain name that is documented in the following issue : https://github.com/spring-media/aws-lambda-router/issues/27
A PR was made a year ago and the solution is now to set removeBasePath to false

Keycloak integration to external identity provider fails when validation tokens with JWKS URL

I'm configuring an external identity provider in my Keycloak instance and trying to get it to validate the tokens using a external JWKS URL. Using the converted PEM from JWKS works fine, the using the URL is not working.
The token validation fails upon login with the following message:
[org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider] (default task-4) Failed to make identity provider oauth callback: org.keycloak.broker.provider.IdentityBrokerException: token signature validation failed
I debugged the Keycloak server get more on the problem and found a "problem" in class JWKSUtils:
/**
* #author Marek Posolda
*/
public class JWKSUtils {
//...
public static Map<String, KeyWrapper> getKeyWrappersForUse(JSONWebKeySet keySet, JWK.Use requestedUse) {
Map<String, KeyWrapper> result = new HashMap<>();
for (JWK jwk : keySet.getKeys()) {
JWKParser parser = JWKParser.create(jwk);
if (jwk.getPublicKeyUse().equals(requestedUse.asString()) && parser.isKeyTypeSupported(jwk.getKeyType())) {
KeyWrapper keyWrapper = new KeyWrapper();
keyWrapper.setKid(jwk.getKeyId());
keyWrapper.setAlgorithm(jwk.getAlgorithm());
keyWrapper.setType(jwk.getKeyType());
keyWrapper.setUse(getKeyUse(jwk.getPublicKeyUse()));
keyWrapper.setVerifyKey(parser.toPublicKey());
result.put(keyWrapper.getKid(), keyWrapper);
}
}
return result;
}
//...
}
The if fails with a NullPointerException because the call jwk.getPublicKeyUse() returns null.
But I found out that it's null because the JWKS URL returns a single key without the attribute use, which is optional according to the specification. [https://www.rfc-editor.org/rfc/rfc7517#section-4.2]
Keycloak only accepts JWKS URLs that return all keys with the attribute use defined. But the IdP I'm trying to connect does not return that attribute in the key.
Given that situation, to who should I file an issue, the IdP or to Keycloak? Or is there something I'm doing wrong in the configuration?
I filed an issue with Keycloak about this exact problem in August 2019.
Their answer:
Consuming keys without validating alg and use is dangerous as such
Keycloak requires these to be present.
In my case, I contacted the IdP and they were able to populate the "use" parameter. If that is not an option, then you're pretty much stuck with your workaround.

How do add an apitoken as part of a custom VSTS service endpoint datasource?

I'm am trying to implement a VSTS extension which adds a new service endpoint. Crucially, the authentication method for this service includes the API as part of the querystring.
I am using the "type": "ms.vss-endpoint.endpoint-auth-scheme-token" for AuthenticationScheme.
I've defined the dataSources like so:
"dataSources": [
{
"name": "TestConnection",
"endpointUrl": "{{endpoint.url}}projects?token={{endpoint.apitoken}}"
}
]
However, in performing a test to Verify Connection:
Failed to query service endpoint api: https://myserver.com/projects?token=.
endpoint.apitoken is always blank.
Is there a placeholder/replacement value that can be used to get access to this value or another way of achieving the same end result?
I've tried using different authentication schemes (such as 'none') and included a inputDescriptor to capture my apitoken, but I have the same result. There doesn't seem to be a way to reference these values?
No, it is not supported. This article may benefit you: Service endpoint authentication schemes

what API Gateway methods support Authorization?

When I create a resource/method in AWS API Gateway API I can create one of the following methods: DELETE, GET, HEAD, OPTIONS, PATCH or POST.
If I choose GET then API Gateway doesn't pass authentication details; but for POST it does.
For GET should I be adding the cognito credentials to the URL of my GET? or just never use GET and use POST for all authenticated calls?
My set-up in API Gateway/Lambda:
I created a Resource and two methods: GET and POST
Under Authorization Settings I set Authorization to AWS_AIM
For this example there is no Request Model
Under Method Execution I set Integration type to Lambda Function and I check Invoke with caller credentials (I also set Lambda Region and Lambda Function)
I leave Credentials cache unchecked.
For Body Mapping Templates, I set Content-Type to `application/json' and the Mapping Template to
{ "identity" : "$input.params('identity')"}
In my Python Lambda function:
def lambda_handler(event, context):
print context.identity
print context.identity.cognito_identity_id
return True
Running the Python function:
For the GET context.identity is None
For the POST context.identity has a value and context.identity.cognito_identity_id has the correct value.
As mentioned in comments: all HTTP methods support authentication. If the method is configured to require authentication, authentication results should be included in the context for you to access via mapping templates to pass down stream as contextual information.
If this is not working for you, please update your question to reflect:
How your API methods are configured.
What your mapping template is.
What results you see in testing.
UPDATE
The code in your lambda function is checking the context of the Lambda function, not the value from API Gateway. To access the value passed in from API Gateway, you would need to use event.identity not context.identity.
This would only half solve your problem as you are not using the correct value to access the identity in API gateway. That would be $context.identity.cognitoIdentityId (assuming you are using Amazon Cognito auth). Please see the mapping template reference for a full guide of supported variables.
Finally, you may want to consider using the template referenced in this question.

IdenityServer3 windows auth support and custom grant flow support

I am looking for IdentityServer3 version which can support windows authentication and customgrant.
I found the windows authentication version: "Windows Auth All-in-One" in github.
Windows token conversion is working fine.
But when I try to use custom grant flow, using the following code:
var client = new TokenClient(
Constants.TokenEndpoint,
"customclient",
"secret");
return client.RequestCustomGrantAsync("custom", "read write", ParameterData).Result;
I am getting the response as:
"error": "unsupported_grant_type"
Any idea how to enable the custom grant type in Windows Auth All-in-One version of Identity server?
Using IdentityServer's extensibility mechanism, you can register a custom grant validator for the my_custom_credential.
The job of a custom grant validator is to validate the incoming data, and map that to an IdentityServer user.
You start by implementing this interface:
public interface ICustomGrantValidator
{
Task<CustomGrantValidationResult> ValidateAsync(ValidatedTokenRequest request);
string GrantType { get; }
}
In the GrantType property you specify which custom grant type you want to handle with this validator.
In the ValidateAsync method you have access to the raw requests (e.g. for reading custom parameters like in the example
above) as well as validated data like scopes and client identity.
The result object allows you to set either a principal (with claims) that map to a user - or an error message.
You register the validator by setting it on the service factory:
factory.CustomGrantValidators.Add(
new Registration<ICustomGrantValidator, MyCustomGrantValidator>());
To use this grant type, you need to create a client with the following configuration:
The Flow must be set to Custom
The AllowedCustomGrantTypes must include the custom grant type
https://identityserver.github.io/Documentation/docsv2/advanced/customGrantTypes.html