2016-02-17 13 views
7

Tôi đang sử dụng tính năng mới của Cổng API có chức năng Lambda để sử dụng Trình ủy quyền tùy chỉnh (https://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html).Giá trị ID chính phù hợp cho Trình ủy quyền tùy chỉnh API Gateway qua Lambda?

Trình ủy quyền sử dụng JWT Tokens để xác thực mã thông báo cho ngữ cảnh và phạm vi người dùng hiện tại. Tất cả đều hoạt động tốt nhưng có một khái niệm về chính sách AWS mà tôi không thể tìm ra từ tài liệu.

Các sản phẩm của một Tuỳ chỉnh ủy quyền chức năng phải được một đối tượng chứa hai điều:

  1. principalId - trong câu hỏi
  2. policyDocument - một tài liệu chính sách có hiệu lực với tuyên bố cho phép người dùng được phép truy cập Tài nguyên, giai đoạn Lambda, v.v.

Bây giờ, ví dụ về quy trình của Người cấp phép tùy chỉnh ntly hiển thị hầu hết các giá trị tùy ý cho biến số principalId. Nhưng nếu tôi đang suy nghĩ một cách chính xác, điều này principalId nên là duy nhất cho mỗi người dùng? Và có lẽ có giá trị duy nhất cụ thể của người dùng được liên kết với nó (chẳng hạn như token.userId hoặc token.email).

Nếu điều này là đúng, sau đó cho mã được cung cấp của tôi dưới đây, nếu JWT Token không hợp lệ, sau đó tôi không có quyền truy cập vào các userId hoặc email, và không có đầu mối gì để thiết lập principalId tới. Tôi tạm thời đặt nó thành user chỉ để có điều gì đó trả lại cho chính sách Từ chối để đảm bảo rằng phản hồi là 403 Forbidden.

Bất kỳ ai có bất kỳ đầu mối nào về các phương pháp hay nhất để đặt principalId cho Trình ủy quyền tùy chỉnh?

var jwt = require('jsonwebtoken'); 
var JWT_SECRET = 'My$ecret!'; 


/** 
* Implicit AWS API Gateway Custom Authorizer. Validates the JWT token passed 
* into the Authorization header for all requests. 
* @param {Object} event [description] 
* @param {Object} context [description] 
* @return {Object}   [description] 
*/ 
exports.handler = function(event, context) { 
    var token = event.authorizationToken; 
    try { 
    var decoded = jwt.verify(token, JWT_SECRET); 
    context.done(null, generatePolicy(decoded.id, 'Allow', 'arn:aws:execute-api:*:*:*')); 
    } catch(ex) { 
    console.error(ex.name + ": " + ex.message); 
    context.done(null, generatePolicy('user', 'Deny', 'arn:aws:execute-api:*:*:*')); 
    } 
}; 

function generatePolicy(principalId, effect, resource) { 
    var authResponse = {}; 
    authResponse.principalId = principalId; 
    if (effect && resource) { 
    var policyDocument = {}; 
    policyDocument.Version = '2012-10-17'; // default version 
    policyDocument.Statement = []; 
    var statementOne = {}; 
    statementOne.Action = 'execute-api:Invoke'; // default action 
    statementOne.Effect = effect; 
    statementOne.Resource = resource; 
    policyDocument.Statement[0] = statementOne; 
    authResponse.policyDocument = policyDocument; 
    } 
    return authResponse; 
} 

Trả lời

5

PrimaryId được dùng để đại diện cho số nhận dạng dài hạn cho bất kỳ thực thể nào được ủy quyền thực hiện cuộc gọi API. Vì vậy, nếu bạn có một cơ sở dữ liệu hiện có của người dùng, mỗi người dùng có lẽ có một định danh duy nhất hoặc tên người dùng. Bạn đã đề cập đến 'người dùng', điều này có lẽ là tốt. Về mặt chức năng, primaryId được ghi lại nếu bạn bật Nhật ký CloudWatch và cũng là những gì bạn có thể truy cập trong bối cảnh $ cho các mẫu ánh xạ.

Về mặt thiết kế cho chức năng của bạn, bạn có hai tùy chọn để xử lý mã thông báo 'không hợp lệ'.

  1. Nếu bạn trả lại chính sách hợp lệ từ chối truy cập, điều này sẽ giúp bạn lưu bộ nhớ chính sách liên kết với mã thông báo trong trường hợp nó được sử dụng lại. Tuy nhiên, khách hàng có thể nhận được 403 và cho rằng mã thông báo hợp lệ nhưng họ không có quyền truy cập vào tài nguyên mà họ yêu cầu.

  2. context.fail("Unauthorized") sẽ gửi phản hồi xấu cho khách hàng, điều này sẽ cho biết rằng mã thông báo không hợp lệ. Điều này sẽ giúp khách hàng, nhưng cũng dẫn đến nhiều invocations trên chức năng nếu khách hàng liên tục phát lại các mã thông báo xấu.bộ nhớ đệm tiêu cực hiện nay là không có sẵn trên tính năng, nhưng một cách khác để cung cấp bảo vệ vừa là sử dụng 'identityValidationExpresion' ->http://docs.aws.amazon.com/apigateway/api-reference/resource/authorizer/#identityValidationExpression

Ngoài ra, tôi rất muốn khuyên bạn nên chuyển này cho một chức năng Lambda mới dựa trên kế hoạch chi tiết apigateway-authorizer-nodejs, vì mẫu mã trong tài liệu là tối thiểu và chỉ dùng để minh họa. Kế hoạch chi tiết có rất nhiều ý kiến ​​ghi lại các cách sử dụng khác nhau, như chức năng thất bại ("Không được phép").

+0

Cảm ơn vì điều này! Tôi vẫn có câu hỏi làm rõ về chỉ primaryId của chính sách được trả lại được tạo. Hãy để tôi chạy qua một kịch bản: 1.) Người dùng đã đăng nhập và có mã thông báo JWT hợp lệ mà giờ đây họ có thể chuyển vào tiêu đề Cấp phép của từng yêu cầu. 2.) Trình ủy quyền tùy chỉnh có thể xác thực mã thông báo và đảm bảo ủy quyền dựa trên tải trọng của JWT đã giải mã. 3.) ID chính hiện có thể giống như: người dùng | 1234-abcd-4312-bcdef Điều này cho phép tôi có số nhận dạng duy nhất cho tất cả các yêu cầu cho người dùng cụ thể này. –

+0

1.) Người dùng chưa đăng nhập và yêu cầu điểm cuối bảo mật trên Cổng API. 2.) Trình ủy quyền tùy chỉnh cố gắng xác minh và giải mã JWT nhưng nó không hợp lệ/null. 3.) Bây giờ, principalId không có định danh duy nhất cho điều này vì tất nhiên đây không phải là người dùng truy cập hợp lệ. Thực tiễn tốt nhất cho giá trị principalId ở đây là gì? Có lẽ người dùng | Tôi đoán cuộc đấu tranh của tôi cũng vậy, nên primaryId là duy nhất cho mỗi người dùng? Hoặc cho mỗi nhóm quyền của người dùng? Và điều gì xảy ra đối với yêu cầu + Người ủy quyền tùy chỉnh * không thành công hoặc trái phép? –

+0

Xin chào Tom, Nếu khách hàng không gửi tiêu đề nào cả, hoặc họ gửi nó với giá trị rỗng/null, API Gateway sẽ gửi lại yêu cầu này với 401 ngay lập tức. Trong trường hợp mã thông báo không hợp lệ, bạn có hai tùy chọn: 1. Nếu bạn muốn lưu trữ kết quả cho mã thông báo không hợp lệ này, "người dùng | Không được phép" là tốt và bạn có thể gửi chính sách Từ chối. 2. Nếu bạn không quan tâm đến bộ nhớ đệm và bạn muốn khách hàng biết rằng mã thông báo của họ không hợp lệ, hãy sử dụng dòng context.fail ("Không được phép") , cho biết rằng khách hàng nên cố gắng đăng nhập hoặc nhận được hợp lệ mã thông báo theo một cách nào đó trước khi thử lại. –

Các vấn đề liên quan