Php-JWT::decode không cần khóa

Tôi muốn sử dụng nhóm người dùng Amazon Cognito làm phương thức xác thực cho ứng dụng của mình. Cách an toàn để xác minh ID và truy cập mã thông báo do khách hàng gửi tới ứng dụng của tôi là gì?

Mô tả ngắn

Khi khách hàng xác thực ứng dụng của bạn bằng nhóm người dùng, Amazon Cognito sẽ gửi mã thông báo ID. Bạn có thể xác minh mã thông báo ID theo cách thủ công trong các trường hợp tương tự như sau

  • Bạn đã tạo một ứng dụng web và muốn sử dụng nhóm người dùng Amazon Cognito để xác thực
  • Bạn sử dụng nhóm người dùng Amazon Cognito để xác thực và nhóm nhận dạng Amazon Cognito để truy xuất thông tin xác thực tạm thời của Dịch vụ mã thông báo bảo mật AWS (AWS STS). AWS Lambda được gọi với các thông tin xác thực đó, nhưng Lambda không có thông tin về người ban đầu được xác thực với nhóm người dùng

Để nhận thông tin chi tiết về người dùng Amazon Cognito có trong Mã thông báo web JSON Cognito của Amazon (JWT), bạn có thể giải mã mã thông báo rồi xác minh chữ ký

Nghị quyết

import { CognitoJwtVerifier } from "aws-jwt-verify";

// Verifier that expects valid access tokens:
const verifier = CognitoJwtVerifier.create({
  userPoolId: "",
  tokenUse: "access",
  clientId: "",
});

try {
  const payload = await verifier.verify(
    "eyJraWQeyJhdF9oYXNoIjoidk..." // the JWT as string
  );
  console.log("Token is valid. Payload:", payload);
} catch {
  console.log("Token not valid!");
}

Sau khi người dùng đăng nhập, nhóm người dùng Amazon Cognito trả về một JWT. JWT là chuỗi JSON được mã hóa base64url ("yêu cầu") chứa thông tin về người dùng. Amazon Cognito trả lại ba mã thông báo. mã thông báo ID, mã thông báo truy cập và mã thông báo làm mới. Mã thông báo ID chứa các trường người dùng được xác định trong nhóm người dùng Amazon Cognito

Mã thông báo bao gồm ba phần. tiêu đề, tải trọng và chữ ký

Sau đây là tiêu đề của mã thông báo ID mẫu. Tiêu đề chứa ID khóa ("kid"), cũng như thuật toán ("alg") được sử dụng để ký mã thông báo. Trong ví dụ này, thuật toán là "RS256", là chữ ký RSA với SHA-256

{
  "kid": "abcdefghijklmnopqrsexample=",
  "alg": "RS256"
}

Sau đây là một ví dụ về tải trọng, có thông tin về người dùng, cũng như dấu thời gian tạo và hết hạn mã thông báo

{
  "sub": "aaaaaaaa-bbbb-cccc-dddd-example",
  "aud": "xxxxxxxxxxxxexample",
  "email_verified": true,
  "token_use": "id",
  "auth_time": 1500009400,
  "iss": "https://cognito-idp.ap-southeast-2.amazonaws.com/ap-southeast-2_example",
  "cognito:username": "anaya",
  "exp": 1500013000,
  "given_name": "Anaya",
  "iat": 1500009400,
  "email": "[email protected]"
}

Phần cuối cùng là chữ ký, là sự kết hợp được băm và mã hóa của tiêu đề và tải trọng

Amazon Cognito tạo hai cặp khóa RSA cho mỗi nhóm người dùng. Khóa riêng của mỗi cặp được sử dụng để ký mã thông báo ID hoặc mã thông báo truy cập tương ứng. Các khóa công khai được cung cấp tại một địa chỉ ở định dạng sau

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

Tệp JSON (jwks. json) được cấu trúc theo định dạng sau

{
    "keys": [{
        "alg": "RS256",
        "e": "AQAB",
        "kid": "abcdefghijklmnopqrsexample=",
        "kty": "RSA",
        "n": "lsjhglskjhgslkjgh43lj5h34lkjh34lkjht3example",
        "use": "sig"
    }, {
        "alg":
        "RS256",
        "e": "AQAB",
        "kid": "fgjhlkhjlkhexample=",
        "kty": "RSA",
        "n": "sgjhlk6jp98ugp98up34hpexample",
        "use": "sig"
    }]
}

Để xác minh chữ ký của Amazon Cognito JWT, trước tiên hãy tìm kiếm khóa chung có ID khóa khớp với ID khóa trong tiêu đề của mã thông báo. Sau đó, bạn có thể sử dụng các thư viện, chẳng hạn như aws-jwt-verify hoặc những thư viện do jwt đề xuất. io hoặc OpenID Foundation, để xác thực chữ ký của mã thông báo và trích xuất các giá trị, chẳng hạn như ngày hết hạn và tên người dùng

Ngoài chữ ký, cách tốt nhất là xác minh những điều sau

  • Mã thông báo chưa hết hạn
  • Đối tượng ("aud") được chỉ định trong tải trọng khớp với ID ứng dụng khách được tạo trong nhóm người dùng Amazon Cognito

Thư viện aws-jwt-verify thay mặt bạn bao gồm các bước kiểm tra này. Để biết thêm ví dụ mã về cách giải mã và xác minh Amazon Cognito JWT bằng Lambda, hãy xem Giải mã và xác minh mã thông báo Amazon Cognito JWT

Tìm ra nó với một số trợ giúp trên Stack Overflow. JWT do Apple trả lại không được ký bằng khóa riêng của tôi, nó được ký bằng khóa chung của Apple. Khóa công khai đó được nhúng trong chứng chỉ trong mảng tiêu đề ['x5c']. Tôi đã phải chuyển đổi dữ liệu chứng chỉ DER được mã hóa base64 đó thành định dạng PEM (có nghĩa là gói nó trong một số văn bản). Sau đó, tôi có thể trích xuất khóa công khai từ chứng chỉ PEM đó. SAU ĐÓ tôi có thể sử dụng nó để xác minh/giải mã

list($headerb64, $bodyb64, $cryptob64) = explode('.', $jwt);
$headertext = JWT::urlsafeB64Decode($headerb64);
$header = JWT::jsonDecode($headertext);
$dercertificateb64 = $header->x5c[0];
$wrappedcertificatetext = trim(chunk_split($dercertificateb64, 64));
$certificate = <<alg));

Tuy nhiên, đây không phải là bước cuối cùng, điều này chỉ xác minh tính nhất quán bên trong của phần tử đầu tiên trong JWT, nhưng không kiểm tra xem nó có thực sự đến từ Apple hay không. Các phần tử khác trong mảng header['x5c'] là chuỗi chứng chỉ cần thiết để hoàn tất quá trình xác minh chuỗi. Mình chưa tìm ra cách làm phần đó

Bạn có thể giải mã JWT mà không cần khóa chung không?

Theo thiết kế, bất kỳ ai cũng có thể giải mã JWT và đọc nội dung của phần tiêu đề và phần tải trọng. Nhưng chúng tôi cần quyền truy cập vào khóa bí mật được sử dụng để tạo chữ ký nhằm xác minh tính toàn vẹn của mã thông báo .

Làm cách nào để giải mã mã thông báo Web JSON trong PHP?

Làm cách nào để giải mã chữ ký JWT? .
Cấu trúc của mã thông báo JWT. Mã thông báo JWT trông như sau
Tách mã thông báo JWT. Mã thông báo nhận được trong yêu cầu phải chứa 3 phần chúng tôi đã đề cập ở trên
Giải mã Base64
Phân tích cú pháp JSON
Kiểm tra dấu thời gian hết hạn
Xác minh chữ ký
Truy cập thông tin Người dùng từ Payload
Thẩm quyền giải quyết

Làm cách nào để tạo khóa bí mật cho JWT trong PHP?

php'; . $secret = getenv('SECRET'); // Create the token header $header = json_encode([ 'typ' => 'JWT', 'alg' => 'HS256' ]); // Create the token payload $payload = json_encode([ 'user_id' => 1, 'role' => 'admin', 'exp' => 1593828222 ]); // Encode Header $base64UrlHeader = base64UrlEncode($ ...

Có ai có thể giải mã JWT không?

Vì mọi người đều có thể đọc được nội dung bên trong mã thông báo, quyền riêng tư nên được tính đến. Nếu bạn muốn đưa dữ liệu nhạy cảm về người dùng vào mã thông báo hoặc thậm chí là Thông tin nhận dạng cá nhân, hãy nhớ rằng bất kỳ ai cũng có thể giải mã mã thông báo và truy cập dữ liệu .