Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ protected APIGatewayProxyFunction(AspNetCoreStartupMode startupMode)

}


/// <summary>
///
/// </summary>
Expand All @@ -86,16 +87,35 @@ protected APIGatewayProxyFunction(StartupMode startupMode)

}


private protected override void InternalPostCreateContext(HostingApplication.Context context, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
private protected override void InternalPostCreateContext(
HostingApplication.Context context,
APIGatewayProxyRequest apiGatewayRequest,
ILambdaContext lambdaContext)
{
if (apiGatewayRequest?.RequestContext?.Authorizer?.Claims != null)
var authorizer = apiGatewayRequest?.RequestContext?.Authorizer;

if (authorizer != null)
{
var identity = new ClaimsIdentity(apiGatewayRequest.RequestContext.Authorizer.Claims.Select(
entry => new Claim(entry.Key, entry.Value.ToString())), "AuthorizerIdentity");
// handling claims output from cognito user pool authorizer
if (authorizer.Claims != null && authorizer.Claims.Count != 0)
{
var identity = new ClaimsIdentity(authorizer.Claims.Select(
entry => new Claim(entry.Key, entry.Value.ToString())), "AuthorizerIdentity");

lambdaContext.Logger.LogLine(
$"Configuring HttpContext.User with {authorizer.Claims.Count} claims coming from API Gateway's Request Context");
context.HttpContext.User = new ClaimsPrincipal(identity);
}
else
{
// handling claims output from custom lambda authorizer
var identity = new ClaimsIdentity(authorizer.Select(
entry => new Claim(entry.Key, entry.Value.ToString())), "AuthorizerIdentity");

_logger.LogDebug($"Configuring HttpContext.User with {apiGatewayRequest.RequestContext.Authorizer.Claims.Count} claims coming from API Gateway's Request Context");
context.HttpContext.User = new ClaimsPrincipal(identity);
lambdaContext.Logger.LogLine(
$"Configuring HttpContext.User with {authorizer.Count} claims coming from API Gateway's Request Context");
context.HttpContext.User = new ClaimsPrincipal(identity);
}
}
}

Expand All @@ -115,12 +135,13 @@ private protected override void InternalCustomResponseExceptionHandling(HostingA
protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxyRequest apiGatewayRequest, ILambdaContext lambdaContext)
{
{
var requestFeatures = (IHttpRequestFeature)features;
var requestFeatures = (IHttpRequestFeature) features;
requestFeatures.Scheme = "https";
requestFeatures.Method = apiGatewayRequest.HttpMethod;

string path = null;
if (apiGatewayRequest.PathParameters != null && apiGatewayRequest.PathParameters.ContainsKey("proxy") && !string.IsNullOrEmpty(apiGatewayRequest.Resource))
if (apiGatewayRequest.PathParameters != null && apiGatewayRequest.PathParameters.ContainsKey("proxy") &&
!string.IsNullOrEmpty(apiGatewayRequest.Resource))
{
var proxyPath = apiGatewayRequest.PathParameters["proxy"];
path = apiGatewayRequest.Resource.Replace("{proxy+}", proxyPath);
Expand Down Expand Up @@ -157,7 +178,8 @@ protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxy

if (requestContextPath.EndsWith(path))
{
requestFeatures.PathBase = requestContextPath.Substring(0, requestContextPath.Length - requestFeatures.Path.Length);
requestFeatures.PathBase = requestContextPath.Substring(0,
requestContextPath.Length - requestFeatures.Path.Length);
}
}

Expand Down Expand Up @@ -190,7 +212,7 @@ protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxy

{
// set up connection features
var connectionFeatures = (IHttpConnectionFeature)features;
var connectionFeatures = (IHttpConnectionFeature) features;

if (!string.IsNullOrEmpty(apiGatewayRequest?.RequestContext?.Identity?.SourceIp) &&
IPAddress.TryParse(apiGatewayRequest.RequestContext.Identity.SourceIp, out var remoteIpAddress))
Expand All @@ -207,7 +229,6 @@ protected override void MarshallRequest(InvokeFeatures features, APIGatewayProxy
// was marshalled into ASP.NET Core request.
PostMarshallConnectionFeature(connectionFeatures, apiGatewayRequest, lambdaContext);
}

}

/// <summary>
Expand Down Expand Up @@ -261,4 +282,4 @@ protected override APIGatewayProxyResponse MarshallResponse(IHttpResponseFeature
return response;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Linq;
using System.Net;
using System.Reflection;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Expand All @@ -33,7 +32,7 @@ public async Task TestGetAllValues()
Assert.True(response.MultiValueHeaders.ContainsKey("Content-Type"));
Assert.Equal("application/json; charset=utf-8", response.MultiValueHeaders["Content-Type"][0]);

Assert.Contains("OnStarting Called", ((TestLambdaLogger)context.Logger).Buffer.ToString());
Assert.Contains("OnStarting Called", ((TestLambdaLogger) context.Logger).Buffer.ToString());
}

[Fact]
Expand Down Expand Up @@ -160,8 +159,9 @@ public void TestCustomAuthorizerSerialization()
new APIGatewayCustomAuthorizerPolicy.IAMPolicyStatement
{
Effect = "Allow",
Action = new HashSet<string> { "execute-api:Invoke" },
Resource = new HashSet<string> { "arn:aws:execute-api:us-west-2:1234567890:apit123d45/Prod/GET/*" }
Action = new HashSet<string> {"execute-api:Invoke"},
Resource = new HashSet<string>
{"arn:aws:execute-api:us-west-2:1234567890:apit123d45/Prod/GET/*"}
}
}
}
Expand All @@ -177,21 +177,21 @@ public void TestCustomAuthorizerSerialization()
public async Task TestGetBinaryContent()
{
var response = await this.InvokeAPIGatewayRequest("values-get-binary-apigatway-request.json");
Assert.Equal((int)HttpStatusCode.OK, response.StatusCode);

Assert.Equal((int) HttpStatusCode.OK, response.StatusCode);

IList<string> contentType;
Assert.True(response.MultiValueHeaders.TryGetValue("Content-Type", out contentType),
"Content-Type response header exists");
Assert.Equal("application/octet-stream", contentType[0]);
Assert.NotNull(response.Body);
Assert.True(response.Body.Length > 0,
"Body content is not empty");
"Body content is not empty");

Assert.True(response.IsBase64Encoded, "Response IsBase64Encoded");

// Compute a 256-byte array, with values 0-255
var binExpected = new byte[byte.MaxValue].Select((val, index) => (byte)index).ToArray();
var binExpected = new byte[byte.MaxValue].Select((val, index) => (byte) index).ToArray();
var binActual = Convert.FromBase64String(response.Body);
Assert.Equal(binExpected, binActual);
}
Expand Down Expand Up @@ -251,6 +251,15 @@ public async Task TestAuthTestAccess()
Assert.Equal("You Have Access", response.Body);
}

[Fact]
public async Task TestAuthTestAccess_CustomLambdaAuthorizerClaims()
{
var response =
await this.InvokeAPIGatewayRequest("authtest-access-request-custom-lambda-authorizer-output.json");

Assert.Equal(200, response.StatusCode);
Assert.Equal("You Have Access", response.Body);
}

[Fact]
public async Task TestAuthTestNoAccess()
Expand Down Expand Up @@ -310,4 +319,4 @@ private async Task<APIGatewayProxyResponse> InvokeAPIGatewayRequest(TestLambdaCo
return await lambdaFunction.FunctionHandlerAsync(request, context);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"resource": "/{proxy+}",
"path": "/api/authtest",
"httpMethod": "GET",
"headers": {
"Authorization": "eyJraWQiOiJLdXprWCtcL0E4MWlVZGU5QSt2SFBMdzZCTUFmQzVqUGJ1NTZiT0VGNXdkaz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI4ZWYzZTQ1NS0zODY5LTQwMmUtYWM5ZS1mODhlODZjMzIwYjMiLCJjb2duaXRvOmdyb3VwcyI6WyJBZG1pbiJdLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLXdlc3QtMi5hbWF6b25hd3MuY29tXC91cy13ZXN0LTJfUExpM2NmMHUwIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjp0cnVlLCJjb2duaXRvOnVzZXJuYW1lIjoibm9ybWoiLCJhdWQiOiIzbXVzaGZjOHNnbTh1b2FjdmlmNXZoa3Q0OSIsImV2ZW50X2lkIjoiNzU3NjBmNTgtZjk4NC0xMWU3LThkNGEtMjM4OWVmYzUwZDY4IiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE1MTU5NzMyOTYsInBob25lX251bWJlciI6IisxNDI1NzM2NzM0OSIsImV4cCI6MTUxNTk3Njg5NiwiaWF0IjoxNTE1OTczMjk2LCJlbWFpbCI6ImpvaGFuc28yQGdtYWlsLmNvbSJ9.v1zIeTutUMzgXGoQy5dpOXUW6km9Ye-X-iLehgn1fO4HeJPZ9rOY9jDRMyRjyF5I57sAsN1v9uB3f98gEdStzO4qpASlYK7F7CtcenJ2lZYNU4gJPDQqEDdoMvE5Nir89RL09PYFceKaZw2Qr53VTLBfwaNGJYeSYeiZN09RL6fXwciH5h15rGwgNpl3kvzZOTLCqHNv3J7Y5POr8BjT2DvqUVJv7X1M5pOzHxWIqtBfAfyhEzZftIDqNKsI_aKZolkRd_UI77dSMNuZokJSAKlEuXc6fNJ556R3xSAhEli5DeZUIMdQLQVB7pIQzRlXvt2M0MMK-uC2d7_kUWAkVg",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "zzqupfvhrk.execute-api.us-west-2.amazonaws.com",
"Via": "1.1 ca79756ec49e2babf1b916300304b2fb.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "3OhHlF5fim8xxjG1-RZEFK4nos0t-JtPu6vvpNkUg9NOcl-Os53gBg==",
"X-Amzn-Trace-Id": "Root=1-5a5beab2-7cd6a52c614f43910ab9be30",
"X-Forwarded-For": "50.35.77.7, 52.46.17.45",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"queryStringParameters": null,
"pathParameters": {
"proxy": "api/authtest"
},
"stageVariables": null,
"requestContext": {
"resourceId": "8gffya",
"authorizer": {
"cognito:groups": "Admin",
"phone_number_verified": "true",
"cognito:username": "normj",
"aud": "3mushfc8sgm8uoacvif5vhkt49",
"event_id": "75760f58-f984-11e7-8d4a-2389efc50d68",
"token_use": "id",
"auth_time": "1515973296",
"you_are_special": "true"
},
"resourcePath": "/{proxy+}",
"httpMethod": "GET",
"requestTime": "14/Jan/2018:23:41:38 +0000",
"path": "/Prod/api/authtest",
"accountId": "626492997873",
"protocol": "HTTP/1.1",
"stage": "Prod",
"requestTimeEpoch": 1515973298687,
"requestId": "7713b963-f984-11e7-b02a-f346964d4540",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"sourceIp": "50.35.77.7",
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": null,
"user": null
},
"apiId": "zzqupfvhrk"
},
"body": null,
"isBase64Encoded": false
}