public AuthPolicy FunctionHandler(TokenAuthorizerContext input, ILambdaContext context) { try { context.Logger.LogLine($"{nameof(input.AuthorizationToken)}: {input.AuthorizationToken}"); context.Logger.LogLine($"{nameof(input.MethodArn)}: {input.MethodArn}"); var tokenValidation = new TokenValidation(context); var principalId = tokenValidation.GetPrincipalId(input.AuthorizationToken); var methodArn = ApiGatewayArn.Parse(input.MethodArn); var apiOptions = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage); var policyBuilder = new AuthPolicyBuilder(principalId, methodArn.AwsAccountId, apiOptions); // Add your API endpoints and their corresponding HTTP verb, that does not require Group authorization policyBuilder.AllowMethod(HttpVerb.Get, "/shop"); policyBuilder.AllowMethod(HttpVerb.Get, "/shop/*"); policyBuilder.AllowMethod(HttpVerb.Get, "/shop/*/products"); policyBuilder.AllowMethod(HttpVerb.Get, "/shop/*/stock"); policyBuilder.AllowMethod(HttpVerb.Post, "/reset"); var groupName = tokenValidation.GroupName; if (groupName == null) { context.Logger.LogLine("No group based authorization needed"); } else { // Replace the "employee" and "manager" group names below with your preferred choice // Add your API endpoints and their corresponding HTTP verb, that requires Group authorization if (groupName.Contains(',')) { var groups = new List <string>(groupName.Split(',')); if (groups.Contains("employee") && groups.Contains("manager")) { policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse"); policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*"); policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*/stock"); policyBuilder.AllowMethod(HttpVerb.Post, "/warehouse/*/stock/*/move/*"); } else { context.Logger.LogLine("Group based authorization failed"); } } else if (groupName == "employee" || groupName == "manager") { switch (groupName) { case "employee": policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse"); policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*"); policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*/stock"); break; case "manager": policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse"); policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*"); policyBuilder.AllowMethod(HttpVerb.Get, "/warehouse/*/stock"); policyBuilder.AllowMethod(HttpVerb.Post, "/warehouse/*/stock/*/move/*"); break; } } else { context.Logger.LogLine("Group based authorization failed"); } } var authResponse = policyBuilder.Build(); authResponse.Context.Add("key", "value"); authResponse.Context.Add("number", 1); authResponse.Context.Add("bool", true); return(authResponse); } catch (Exception ex) { context.Logger.LogLine(ex.ToString()); throw new Exception("Unauthorized"); } }
public AuthPolicy FunctionHandler(TokenAuthorizerContext input, ILambdaContext context) { try { context.Logger.LogLine($"{nameof(input.AuthorizationToken)}: {input.AuthorizationToken}"); context.Logger.LogLine($"{nameof(input.MethodArn)}: {input.MethodArn}"); // validate the incoming token // and produce the principal user identifier associated with the token // this could be accomplished in a number of ways: // 1. Call out to OAuth provider // 2. Decode a JWT token inline // 3. Lookup in a self-managed DB var principalId = "user|a1b2c3d4"; // you can send a 401 Unauthorized response to the client by failing like so: // throw new Exception("Unauthorized"); // if the token is valid, a policy must be generated which will allow or deny access to the client // if access is denied, the client will receive a 403 Access Denied response // if access is allowed, API Gateway will proceed with the backend integration configured on the method that was called // build apiOptions for the AuthPolicy var methodArn = ApiGatewayArn.Parse(input.MethodArn); var apiOptions = new ApiOptions(methodArn.Region, methodArn.RestApiId, methodArn.Stage); // this function must generate a policy that is associated with the recognized principal user identifier. // depending on your use case, you might store policies in a DB, or generate them on the fly // keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer) // and will apply to subsequent calls to any method/resource in the RestApi // made with the same token // the example policy below denies access to all resources in the RestApi var policyBuilder = new AuthPolicyBuilder(principalId, methodArn.AwsAccountId, apiOptions); policyBuilder.DenyAllMethods(); // policyBuilder.AllowMethod(HttpVerb.GET, "/users/username"); // finally, build the policy var authResponse = policyBuilder.Build(); // new! -- add additional key-value pairs // these are made available by APIGW like so: $context.authorizer.<key> // additional context is cached authResponse.Context.Add("key", "value"); // $context.authorizer.key -> value authResponse.Context.Add("number", 1); authResponse.Context.Add("bool", true); return(authResponse); } catch (Exception ex) { if (ex is UnauthorizedException) { throw; } // log the exception and return a 401 context.Logger.LogLine(ex.ToString()); throw new UnauthorizedException(); } }