Skip to content

Commit

Permalink
First import of User Pool Authorizers support to address issue #24
Browse files Browse the repository at this point in the history
  • Loading branch information
sapessi committed Apr 19, 2017
1 parent d1a8ff2 commit 40c6069
Show file tree
Hide file tree
Showing 7 changed files with 406 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,57 @@
*/
package com.amazonaws.serverless.proxy.internal.model;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;

import java.util.HashMap;
import java.util.Map;


/**
* Custom authorizer context object for the API Gateway request context.
* Context object used for custom authorizers and Cognito User Pool authorizers.
* <p>
* Custom authorizers populate the <code>principalId</code> field. All other custom values
* returned by the authorizer are accessible via the <code>getContextValue</code> method.
* </p>
* <p>
* Cognito User Pool authorizers populate the <pre>claims</pre> object.
* </p>
*/
public class ApiGatewayAuthorizerContext extends HashMap<String, String> {
public class ApiGatewayAuthorizerContext {

private Map<String, String> contextProperties = new HashMap<>();
private String principalId;
private CognitoAuthorizerClaims claims;

//-------------------------------------------------------------
// Methods - Getter/Setter
//-------------------------------------------------------------

public String getPrincipalId() {
return get("principalId");
return principalId;
}


public void setPrincipalId(String principalId) {
put("principalId", principalId);
this.principalId = principalId;
}

@JsonAnyGetter
public String getContextValue(String key) {
return get(key);
return contextProperties.get(key);
}

@JsonAnySetter
public void setContextValue(String key, String value) {
contextProperties.put(key, value);
}


public CognitoAuthorizerClaims getClaims() {
return claims;
}

public void setClaims(CognitoAuthorizerClaims claims) {
this.claims = claims;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import java.util.Map;

/**
* Default implementation of the request object from an API GAteway AWS_PROXY integration
* Default implementation of the request object from an API Gateway AWS_PROXY integration
*/
public class AwsProxyRequest {

Expand Down Expand Up @@ -152,7 +152,7 @@ public boolean isBase64Encoded() {
}


public void setBase64Encoded(boolean base64Encoded) {
public void setIsBase64Encoded(boolean base64Encoded) {
isBase64Encoded = base64Encoded;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
package com.amazonaws.serverless.proxy.internal.model;


import com.fasterxml.jackson.annotation.JsonProperty;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;


/**
* This object represents the claims property in the authorizer context of a request. The claims object is normally populated
* by a Cognito User Pool authorizer and contains the following fields:
* <pre>
* "claims": {
* "sub": "42df3b02-29f1-4779-a3e5-eff92ff280b2",
* "aud": "2k3no2j1rjjbqaskc4bk0ub29b",
* "email_verified": "true",
* "token_use": "id",
* "auth_time": "1492467169",
* "iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_Adx5ZHePg",
* "cognito:username": "sapessi",
* "exp": "Mon Apr 17 23:12:49 UTC 2017",
* "iat": "Mon Apr 17 22:12:49 UTC 2017",
* "email": "[email protected]"
* }
* </pre>
*/
public class CognitoAuthorizerClaims {
// Mon Apr 17 23:12:49 UTC 2017
static final DateTimeFormatter TOKEN_DATE_FORMATTER = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy");

@JsonProperty(value = "sub")
private String subject;
@JsonProperty(value = "aud")
private String audience;
@JsonProperty(value = "iss")
private String issuer;
@JsonProperty(value = "token_use")
private String tokenUse;
@JsonProperty(value = "cognito:username")
private String username;
private String email;
@JsonProperty(value = "email_verified")
private boolean emailVerified;
@JsonProperty(value = "auth_time")
private Long authTime;
private String exp;
private String iat;

private String getSubject() { return this.subject; }

public void setSubject(String subject) {
this.subject = subject;
}


public String getAudience() {
return audience;
}


public void setAudience(String audience) {
this.audience = audience;
}


public String getIssuer() {
return issuer;
}


public void setIssuer(String issuer) {
this.issuer = issuer;
}


public String getTokenUse() {
return tokenUse;
}


public void setTokenUse(String tokenUse) {
this.tokenUse = tokenUse;
}


public String getUsername() {
return username;
}


public void setUsername(String username) {
this.username = username;
}


public String getEmail() {
return email;
}


public void setEmail(String email) {
this.email = email;
}


public boolean isEmailVerified() {
return emailVerified;
}


public void setEmailVerified(boolean emailVerified) {
this.emailVerified = emailVerified;
}


public Long getAuthTime() {
return authTime;
}


public void setAuthTime(Long authTime) {
this.authTime = authTime;
}


public String getExp() {
return exp;
}


public void setExp(String expiration) {
this.exp = expiration;
}

public ZonedDateTime getExpirationTime() {
return ZonedDateTime.from(TOKEN_DATE_FORMATTER.parse(getExp()));
}


public String getIat() {
return iat;
}


public void setIat(String issuedAt) {
this.iat = issuedAt;
}

public ZonedDateTime getIssueTime() {
return ZonedDateTime.from((TOKEN_DATE_FORMATTER.parse(getIat())));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ protected List<Map.Entry<String, String>> parseHeaderValue(String headerValue) {
if (headerValue == null) {
return values;
}
int entryCounter = 1;
for (String kv : headerValue.split(HEADER_VALUE_SEPARATOR)) {
String[] kvSplit = kv.split(HEADER_KEY_VALUE_SEPARATOR);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;

/**
Expand Down Expand Up @@ -156,7 +159,7 @@ public AwsProxyRequestBuilder authorizerContextValue(String key, String value) {
if (this.request.getRequestContext().getAuthorizer() == null) {
this.request.getRequestContext().setAuthorizer(new ApiGatewayAuthorizerContext());
}
this.request.getRequestContext().getAuthorizer().put(key, value);
this.request.getRequestContext().getAuthorizer().setContextValue(key, value);
return this;
}

Expand Down Expand Up @@ -209,6 +212,18 @@ public AwsProxyRequestBuilder serverName(String serverName) {
return this;
}

public AwsProxyRequestBuilder fromJsonString(String jsonContent)
throws IOException {
request = mapper.readValue(jsonContent, AwsProxyRequest.class);
return this;
}

public AwsProxyRequestBuilder fromJsonPath(String filePath)
throws IOException {
request = mapper.readValue(new File(filePath), AwsProxyRequest.class);
return this;
}

public AwsProxyRequest build() {
return this.request;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.amazonaws.serverless.proxy.internal.model;

import com.amazonaws.serverless.proxy.internal.testutils.AwsProxyRequestBuilder;

import org.junit.Test;

import java.io.IOException;

import static org.junit.Assert.*;

public class ApiGatewayAuthorizerContextTest {
private static final String FIELD_NAME_1 = "CUSTOM_FIELD_1";
private static final String FIELD_NAME_2 = "CUSTOM_FIELD_2";
private static final String FIELD_VALUE_1 = "VALUE_1";
private static final String FIELD_VALUE_2 = "VALUE_2";
private static final String PRINCIPAL = "xxxxx";

private static final String AUTHORIZER_REQUEST = "{\n"
+ " \"resource\": \"/restaurants\",\n"
+ " \"path\": \"/restaurants\",\n"
+ " \"httpMethod\": \"GET\",\n"
+ " \"headers\": {\n"
+ " \"Accept\": \"*/*\",\n"
+ " \"Authorization\": \"eyJraWQiOiJKSm9VQUtrRThcL3NTU3Rwa3dPZTFWN2dvak1xS0k1NU8zTzB4WVgwMGNRdz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI0MmRmM2IwMi0yOWYxLTQ3NzktYTNlNS1lZmY5MmZmMjgwYjIiLCJhdWQiOiIyazNubzJqMXJqamJxYXNrYzRiazB1YjI5YiIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTQ5MjQ2NzE2OSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMi5hbWF6b25hd3MuY29tXC91cy1lYXN0LTJfQWR4NVpIZVBnIiwiY29nbml0bzp1c2VybmFtZSI6InNhcGVzc2kiLCJleHAiOjE0OTI0NzA3NjksImlhdCI6MTQ5MjQ2NzE2OSwiZW1haWwiOiJidWxpYW5pc0BhbWF6b24uY29tIn0.aTODUMNib_pQhad1aWTHrlz7kwA5QkcvZptcbLFY5BuNqpr9zsK14EhHRvmvflK4MMQaxCE5Cxa9joR9g-HCmmF1usZhXO4Q2iyEWcBk0whjn3CnC55k6yEuMv6y9krts0YHSamsRkhW7wnCpuLmk2KgzHTfyt6oQ1qbg9QE8l9LRhjCHLnujlLIQaG9p9UfJVf-uGSg1k_bCyzl48lqkc7LDwqDZCHXGf1RYRQLg5jphXF_tjByDk_0t9Ah7pX2nFwl0SUz74enG8emq58g4pemeVekb9Mw0wyD-B5TWeGVs_nvmC3q4jgxMyJy3Xq4Ggd9qSgIN_Khdg3Q26F2bA\",\n"
+ " \"CloudFront-Forwarded-Proto\": \"https\"\n"
+ " },\n"
+ " \"queryStringParameters\": null,\n"
+ " \"pathParameters\": null,\n"
+ " \"stageVariables\": null,\n"
+ " \"requestContext\": {\n"
+ " \"accountId\": \"XXXXXXXXXXXXXX\",\n"
+ " \"resourceId\": \"xxxxx\",\n"
+ " \"stage\": \"dev\",\n"
+ " \"authorizer\": {\n"
+ " \"principalId\": \"" + PRINCIPAL + "\",\n"
+ " \"" + FIELD_NAME_1 + "\": \"" + FIELD_VALUE_1 + "\","
+ " \"" + FIELD_NAME_2 + "\": \"" + FIELD_VALUE_2 + "\""
+ " },\n"
+ " \"requestId\": \"ad0a33ba-23bc-11e7-9b7d-235a67eb05bd\",\n"
+ " \"identity\": {\n"
+ " \"cognitoIdentityPoolId\": null,\n"
+ " \"accountId\": null,\n"
+ " \"cognitoIdentityId\": null,\n"
+ " \"caller\": null,\n"
+ " \"apiKey\": null,\n"
+ " \"sourceIp\": \"54.240.196.171\",\n"
+ " \"accessKey\": null,\n"
+ " \"cognitoAuthenticationType\": null,\n"
+ " \"cognitoAuthenticationProvider\": null,\n"
+ " \"userArn\": null,\n"
+ " \"userAgent\": \"PostmanRuntime/3.0.1\",\n"
+ " \"user\": null\n"
+ " },\n"
+ " \"resourcePath\": \"/restaurants\",\n"
+ " \"httpMethod\": \"GET\",\n"
+ " \"apiId\": \"xxxxxxxx\"\n"
+ " },\n"
+ " \"body\": null,\n"
+ " \"isBase64Encoded\": false\n"
+ "}";

@Test
public void authorizerContext_serialize_customValues() {
try {
AwsProxyRequest req = new AwsProxyRequestBuilder().fromJsonString(AUTHORIZER_REQUEST).build();

assertNotNull(req.getRequestContext().getAuthorizer().getContextValue(FIELD_NAME_1));
assertNotNull(req.getRequestContext().getAuthorizer().getContextValue(FIELD_NAME_2));
assertEquals(FIELD_VALUE_1, req.getRequestContext().getAuthorizer().getContextValue(FIELD_NAME_1));
assertEquals(FIELD_VALUE_2, req.getRequestContext().getAuthorizer().getContextValue(FIELD_NAME_2));
assertEquals(PRINCIPAL, req.getRequestContext().getAuthorizer().getPrincipalId());
assertNull(req.getRequestContext().getAuthorizer().getContextValue("principalId"));
} catch (IOException e) {
e.printStackTrace();
fail();
}
}
}
Loading

0 comments on commit 40c6069

Please sign in to comment.