Hướng dẫn oauth implementation in php
Vietnamese (Tiếng Việt) translation by Andrea Ho (you can also view the original English article) Show Nội dung chính
Trong bài viết này, chúng ta sẽ khám phá Auth0, là một dịch vụ cung cấp xác thực và ủy quyền. Auth0 cho phép bạn thiết lập các tính năng xác thực và ủy quyền cơ bản cho ứng dụng của bạn trong nháy mắt. Auth0 là gì?Auth0 là một công cụ dịch vụ xác thực giúp việc triển khai các tính năng liên quan đến xác thực trong website của bạn trở nên dễ dàng. Nếu bạn đã xây dựng một ứng dụng và bạn chỉ muốn thuê ngoài các tính năng xác thực và ủy quyền , vậy bạn nên cân nhắc sử dụng một dịch vụ như Auth0. Hãy để tôi nhanh chóng tóm tắt Auth0 cung cấp những tính năng gì:
Trong bài viết này, chúng tôi sẽ giới thiệu một số phương pháp đăng nhập một lần (sso) mà bạn có thể triển khai trong các ứng dụng web của mình để tận dụng các tính năng xác thực do dịch vụ Auth0 cung cấp. Trong phần đầu của bài viết, chúng tôi sẽ nghiên cứu cách thiết lập chức năng xác thực cơ bản trong ứng dụng web PHP từ phía máy chủ. Trong phần còn lại, tôi sẽ giải thích cách làm thế nào để bạn có thể bảo mật các API tùy biến của mình bằng cách thiết lập ủy quyền OAuth bằng dịch vụ Auth0. Tích hợp xác thực phía máy chủTrong phần này, chúng tôi sẽ giới thiệu cho các bạn cách nhanh chóng thiết lập xác thực cơ bản cho các ứng dụng web từ phía máy chủ bằng cách sử dụng Auth0. Trong thực tế, đội ngũ Auth0 đã hỗ trợ một sample trên GitHub để minh hoạ các ví dụ cơ bản, vậy chúng tôi sẽ sử dụng chúng thay vì phải tự tạo các ví dụ mới. Trước khi tiếp tục, hãy bảo đảm Composer đã được thiết lập để cài đặt các SDK Auth0 bằng cách sử dụng file Thiết lập dự ánHãy clone những ví dụ của dự án mẫu. git clone https://github.com/auth0-samples/auth0-php-web-app.git . Tiếp
tục chạy lệnh cd 00-Starter-Seed composer install Theo file composer.json, cần cài đặt các gói { "name": "auth0/basic-webapp-sample", "description": "Basic sample for securing a WebApp with Auth0", "require": { "vlucas/phpdotenv": "2.4.0", "auth0/auth0-php": "~5.0" }, "license": "MIT", "authors": [ { "name": "Martin Gontovnikas", "email": "" }, { "name": "Germán Lena", "email": "" } ] } Thư viện Mặt khác, gói Tiếp theo, hãy thiết lập cấu hình cho ứng dụng của chúng ta trong file .env. Tiếp tục tạo file .env bằng cách copy nó từ file .env.example. cp .env.example .env File này chứa các giá trị cấu hình sẽ được thư viện Auth0 sử dụng. AUTH0_CLIENT_ID={CLIENT_ID} AUTH0_DOMAIN={DOMAIN_NAME} AUTH0_CLIENT_SECRET={CLIENT_SECRET} AUTH0_CALLBACK_URL={CALLBACK_URL} AUTH0_AUDIENCE= Bạn sẽ có thể tìm thấy hầu hết các thiết lập trong Applications > Default App > Settings trên trang dashboard của của Auth0. Chú ý rằng tôi đang sử dụng ứng dụng mặc định hệ thống tạo ra. Tất nhiên, bạn có thể tiếp tục và tạo một ứng dụng mới nếu bạn muốn thế.
Bạn sẽ tìm thấy 3 file chủ chốt để thực hiện hầu hết logic xác thực.
Những file chủ yếu của dự ánHãy điểm qua từng file lúc ban động của dự án. Login ScriptChúng ta sẽ bắt đầu với file login.php. $domain, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'audience' => $audience, 'scope' => 'openid profile', 'persist_id_token' => true, 'persist_access_token' => true, 'persist_refresh_token' => true, ]); $auth0->login(); Lúc đầu, chúng tôi đã bao gồm các autoloaders; các file này đảm nhiệm việc tải Auth0 và các class có liên quan đến các biến môi trường. Tiếp theo, chúng ta khởi tạo các biến định cấu hình từ file .env thông qua hàm Tiếp theo, chúng tôi khởi tạo đối tượng Auth0 và gọi phương thức đăng nhập để chuyển hướng người dùng đến Auth0 cho việc đăng nhập. Khi đăng nhập, người dùng sẽ được chuyển hướng trở lại website của chúng tôi. Bạn có thể đăng nhập bằng tài khoản xã hội như Facebook, Google và các tài khoản tương tự hoặc tạo tài khoản mới trong khi đăng nhập. Trong cả hai trường hợp, Auth0 sẽ tạo các bản ghi cho người dùng mới ở trên thiết bị của họ. Bạn có thể bật các đăng nhập qua xã hội khác nhau trong phần Connections > Social trên trang dashboard của Auth0. Ngoài ra, bạn có thể kiểm tra danh sách người dùng đã đăng nhập bằng cách sử dụng Auth0 trên trang dashboard của Auth0 bên dưới liên kết Users. The Logout ScriptTiếp theo, chúng ta hãy xem nhanh file logout.php. $domain, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'audience' => $audience, 'scope' => 'openid profile', 'persist_id_token' => true, 'persist_refresh_token' => true, ]); $auth0->logout(); $return_to = 'https://' . $_SERVER['HTTP_HOST']; $logout_url = sprintf('http://%s/v2/logout?client_id=%s&returnTo=%s', $domain, $client_id, $return_to); header('Location: ' . $logout_url); die(); File này hoạt động khá giống với file login.php, ngoại trừ việc nó sẽ được gọi khi người dùng đăng xuất. Phương thức The Index FileCuối cùng, chúng ta hãy xem qua file index.php, đây là entry point (điểm bắt đầu) của ứng dụng. $domain, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'audience' => $audience, 'scope' => 'openid profile', 'persist_id_token' => true, 'persist_access_token' => true, 'persist_refresh_token' => true, ]); $userInfo = $auth0->getUser(); ?> Ở đây, chúng tôi đã sử dụng phương thức Vậy đấy là phần triển khai luồng xác thực cơ bản cho ứng dụng từ máy chủ. Bảo mật cho API tùy biến của bạn cùng OAuth2Trong phần này, chúng tôi sẽ xem làm sao bạn có thể bảo mật các API tùy chỉnh của mình bằng cách triển khai luồng cấp phép code OAuth2. Tôi hy vọng bạn đã quen thuộc với quy trình cấp phép chuẩn của mã ủy quyền vì chúng tôi sẽ bàn vào chi tiết về việc đó. Hãy xem một số bài viết khác của chúng tôi ở đây trên Envato Tuts+ nếu bạn muốn tìm hiểu về OAuth2. Thay vào đó, chúng tôi sẽ lập tức đào sâu vào việc triển khai thực tế. Hãy tiếp tục tạo file auth_code_grant_example.php với các nội dung như sau. '{AUDIENCE}', 'scope' => 'profile', 'response_type' => 'code', 'client_id' => '{CLIENT_ID}', 'state' => 'SomeRandomString', 'redirect_uri' => '{CALLBACK_URL}' ); $_SESSION['oauth2state']=$params['state']; $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } ?> Sign In 'authorization_code', 'client_id' => '{CLIENT_ID}', 'client_secret' => '{CLIENT_SECRET}', 'code' => $_GET['code'], 'redirect_uri' => '{CALLBACK_URL}' ); $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://{AUTH0_DOMAIN}/oauth/token", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $str_params )); $curl_response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl); if ($curl_error) { echo "Error in the CURL response:" . $curl_error; } else { $arr_json_data = json_decode($curl_response); if (isset($arr_json_data->access_token)) { $access_token = $arr_json_data->access_token; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "http://{YOUR_API_DOMAIN}/demo_api_server.php", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "Authorization: Bearer {$access_token}" ) )); $curl_response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl); if ($curl_error) { echo "Error in the CURL response from DEMO API:" . $curl_error; } else { echo "Demo API Response:" . $curl_response; } } else { echo 'Invalid response, no access token was found.'; } } } Chúng ta hãy xem code này hoạt động như thế nào! Đầu tiên, chúng tôi đã chuẩn bị một liên kết gửi người dùng đến máy chủ Auth0 để bắt đầu luồng ủy quyền. // Check if we need to show the "Sign In" link $params = array ( 'audience' => '{AUDIENCE}', 'scope' => 'profile', 'response_type' => 'code', 'client_id' => '{CLIENT_ID}', 'state' => '{SOME_RANDOM_STRING}', 'redirect_uri' => '{CALLBACK_URL}' ); $_SESSION['oauth2state']=$params['state']; $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } ?> Sign In Hãy thay thế {SOME_RANDOM_STRING} nên được thay thế bằng một giá trị duy nhất và phải khó đoán. Chuỗi này được
sử dụng để ngăn chặn các cuộc tấn công CSRF. Ngoài ra, hãy đảm bảo việc thay thế Nhận Access Token (mã truy cập)Khi người dùng nhấp vào liên kết Sign In, họ sẽ được đưa đến máy chủ Auth0 để xác thực. Sau khi xác thực, họ sẽ được yêu cầu cho phép ứng dụng truy cập vào trang hồ sơ của bạn. Sau khi ủy quyền, người dùng sẽ được chuyển hướng trở lại ứng dụng của bạn với
Tiếp theo, chúng ta có thể trao đổi // If the auth "code" is present in the $_GET // let's exchange it for the access token $params = array ( 'grant_type' => 'authorization_code', 'client_id' => '{CLIENT_ID}', 'client_secret' => '{CLIENT_SECRET}', 'code' => $_GET['code'], 'redirect_uri' => '{CALLBACK_URL}' ); $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } $curl = curl_init(); $curl_response = curl_exec($curl); curl_setopt_array($curl, array( CURLOPT_URL => "https://{AUTH0_DOMAIN}/oauth/token", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $str_params )); Như bạn có thể thấy, cần phải call CURL để lấy access token. Gọi API Endpoint tuỳ biến của bạnKhi bạn có access token, bạn có thể gọi API endpoint tùy biến của mình bằng cách bao gồm nó vào header. $access_token = $arr_json_data->access_token; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "http://{YOUR_API_DOMAIN}/demo_api_server.php", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "Authorization: Bearer {$access_token}" ) )); $curl_response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl); if ($curl_error) { echo "Error in the CURL response from DEMO API:" . $curl_error; } else { echo "Demo API Response:" . $curl_response; } Một API Endpoint được Auth0 bảo vệFile API tài nguyên ảo demo_api_server.php có thể trông như sau: ['{HASHING_ALGORITHM}'], 'valid_audiences' => ['{AUDIENCE}'], 'authorized_iss' => ['{DOMAIN}'] ]); $access_token = getBearerToken(); $token_info = $verifier->verifyAndDecode($access_token); echo json_encode(array('date'=>'API Resource Data!!')); } catch(\Auth0\SDK\Exception\CoreException $e) { throw $e; echo json_encode(array('error'=>$e->getMessage())); } function getAuthorizationHeader() { $headers = null; if (isset($_SERVER['Authorization'])) { $headers = trim($_SERVER["Authorization"]); } else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI $headers = trim($_SERVER["HTTP_AUTHORIZATION"]); } elseif (function_exists('apache_request_headers')) { $requestHeaders = apache_request_headers(); // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); //print_r($requestHeaders); if (isset($requestHeaders['Authorization'])) { $headers = trim($requestHeaders['Authorization']); } } return $headers; } function getBearerToken() { $headers = getAuthorizationHeader(); // HEADER: Get the access token from the header if (!empty($headers)) { if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { return $matches[1]; } } return null; } Hãy nhanh chóng xem kỹ các phần quan trọng của code này. Xác thực Access TokenBạn có trách nhiệm xác thực access token trước khi cấp quyền truy cập vào tài nguyên đang được bảo vệ. Đó chính xác là những gì chúng tôi đã làm trong đoạn đoạn code sau. Chúng tôi đã sử dụng class tiện ích try { $verifier = new JWTVerifier([ 'supported_algs' => ['{SIGNING_ALGORITHM}'], 'valid_audiences' => ['{AUDIENCE}'], 'authorized_iss' => ['{DOMAIN}'] ]); $access_token = getBearerToken(); $token_info = $verifier->verifyAndDecode($access_token); echo json_encode(array('date'=>'API Resource Data!!')); } catch(\Auth0\SDK\Exception\CoreException $e) { throw $e; echo json_encode(array('error'=>$e->getMessage())); }
Vậy đó là cách bạn có thể bảo vệ các API tùy chỉnh của mình nếu muốn sử dụng luồng OAuth2 của dịch vụ Auth0. Tổng kếtHôm nay, chúng tôi xem xét qua dịch vụ Auth0, nó cung cấp xác thực và ủy quyền làm dịch vụ. Sau khi giới thiệu dịch vụ Auth0, chúng tôi đi vào một vài ví dụ thực tế để trình bày cách làm thế nào bạn có thể tích hợp Auth0 với ứng dụng PHP của bạn. Vui lòng gửi đề xuất và câu hỏi của bạn thông qua feed bên dưới đây! |