1. SAML là gì?
Nếu bạn đã từng nghe OAuth hay OAuth2 thì SAML chính là một chuẩn khác để giải quyết bài toán tương tự với OAuth và OAuth2.
Bài toán mà các chuẩn trên giải quyết tên là SSO (Single Sign On).
SSO nảy sinh từ vấn đề khi các nhà cung cấp dịch vụ muốn người dùng có thể sử dụng các dịch vụ khác nhau mà chỉ cần đăng nhập vào một chỗ duy nhất, giúp cho việc sử dụng được thuận tiện cũng như giúp cho người dùng quản lý các username và password được giảm đi tối thiểu, thì đòi hỏi cần có một cách nào đó có thể xác thực và ủy quyền thông tin người dùng mà không cần bắt họ tạo tài khoản khác nhau trên những dịch vụ khác nhau.
Chú ý: SAML tự động giải quyết cả 2 vấn đề xác thực (authentication) và ủy quyền (authorization) nhưng OAuth và OAuth2 chỉ tự động giải quyết được vấn đề uỷ quyền (link tham khảo tại đây).
SAML (Security Assertion Markup Language) là một "chuẩn mở" cho phép nhà cung cấp thực thể (Identity Provider - IdP) xác thực người dùng và ủy quyền cho người dùng sử dụng một dịch vụ nào đó của nhà cung cấp dịch vụ (Service Provider - SP) mà không bắt buộc người dùng phải tạo tài khoản đăng nhập vào dịch vụ đó.
Định nghĩa như trên đọc sẽ khó hiểu, nhưng nếu bạn biết nút "Đăng nhập bằng Facebook" ở một số website thì mục đích của cái nút đó chính là mục đích của SAML.
2. Cách hoạt động của SAML.
Ở hình trên thì: SP là nhà cung cấp dịch vụ (là ứng dụng có nút "Đăng nhập bằng Facebook" ấy), IdP là nhà cung cấp các thực thể (tài khoản người dùng - IdP ở đây là Facebook đấy).
- Bước 1: User sẽ click vào nút "Đăng nhập bằng tài khoản của cái gì đó" từ browser, request này sẽ được gửi tới SP.
- Bước 2: Phía SP sẽ tạo ra một SAML Request để gửi tới IdP, SAML Request này sẽ được chính SP ký điện tử (sign) bằng chữ ký của SP (chữ ký của SP ở đây chính là khóa bí mật của SP).
- Bước 3: Phía IdP khi nhận được SAML Request từ SP sẽ phải xác thực chữ ký có đúng là của SP hay không bằng cách dùng khóa công khai của SP để xác thực:
Khóa công khai của SP này IdP lấy từ đâu?
Trước khi thực hiện giao dịch, SP và IdP phải bằng cách nào đó trao đổi được khóa công khai với nhau trước (không phải khóa bí mật nhé). Thông thường, mỗi bên SP và IdP sẽ có một public url chứa metadata, metadata này chứa các thông tin công khai như là khóa công khai, ID thực thể và URL để điều hướng khi có request đến. Phía IdP sẽ biết được metadata url của SP để từ đó lấy ra khóa công khai của SP để xác thực chữ ký của SP. Trong trường hợp hệ thống của Idp đã có sẵn và không lấy public key của SP thông qua metadata url được thì SP phải gửi khóa công khai của mình cho Idp cài đặt trước khi thực hiện giao dịch.
- Bước 4: Vẫn đang ở IdP, sau khi xác thực được chữ ký của SP rồi, IdP sẽ làm những thứ sau:
- Lấy ra thông tin người dùng đang sử dụng browser (nếu người dùng đang đăng nhập vào IdP, còn nếu người dùng đang không đăng nhập thì bắt người dùng đăng nhập trước) để redirect (http post) về cho SP sử dụng (kết quả trả về này mình gọi là SAML Response). Trước khi gửi về cho SP thì IdP sẽ ký điện tử (sign) vào SAML Response bằng khóa bí mật của IdP.
- Không những IdP ký vào SAML Response mà IdP cũng sẽ mã hóa các kết quả dữ liệu (SAML Assertions) có trong SAML Response bằng khóa công khai của SP.
- Bước 5: Khi SP nhận được SAML Response, nó sẽ thực hiện những việc sau:
- Dùng khóa công khai của IdP để xác thực xem có đúng là kết quả được gửi từ IdP hay không (đây chính là phần xác thực mà OAuth và OAuth2 không có). Khóa công khai của IdP cũng giống như nói ở trên, có thể lấy thông qua metadata url của IdP hoặc có thể được trao đổi trước.
- Nếu xác thực đúng chữ ký, SP sẽ tiếp tục dùng khóa công khai của chính mình để giải mãi SAML Assertions đã được mã hóa từ phía IdP.
- Lấy các thông tin dữ liệu người dùng trong SAML Assertions để đăng nhập người dùng vào hệ thống của chính mình, và trả về cho người dùng thông báo thành công (hay điều hướng người dùng tới các tài nguyên mong muốn).
Phía trên mình đã trình bày lý thuyết phần hoạt động của SAML, dưới đây là phần thực hành sử dụng SP là server Rails và IdP là Okta.
3. Cấu hình SAML trong Rails sử dụng IdP là Okta.
Trong trường hợp này: Ứng dụng Rails của bạn chính là SP, và ứng dụng bạn tạo trên Okta chính là Idp.
3.1. Cấu hình trong Rails.
- Cài đặt và sử dụng gem https://github.com/onelogin/ruby-saml
- Source code trong rails:
Cơ bản source code trong rails chỉ có như trên thôi. Phần cài đặt của SAML nằm trong method saml_settings
:
- Url của metadata của IdP chính là url nằm trong câu lệnh
idp_metadata_parser.parse_remote(...)
. settings.issuer
chính là SP identity, là tên của thưc thể SP, thường nó sẽ được gán cho giá trị là url của metadata của SP. Sau khi cài đặt xong bạn truy cập vào đường linkhttp://localhost/mrs/saml/metadata
thì nó sẽ tự động render ra dữ liệu metadata cho bạn.assertion_cosumer_service_url
là url để IdP trả kết quả lại cho SP. Khi SP nhận kết quả từ IdP, nó sẽ so sánh url có trong SAML Response với url này để xác thực xem có đúng kết quả được trả về đúng địa chỉ không, nếu không đúng sẽ báo lỗi.settings.certificate
là khóa công khai của SP, SP phải khai báo nó ở đây để xác thực chữ ký của IdP.- Với method
metadata
ở trên thì khi bạn truy cập vàohttp://localhost/mrs/saml/metadata
, mọi thông tin cần thiết khai báo trongsaml_settings
sẽ được public ra internet (những thông tin bí mật sẽ không được công khai). settings.private_key
là khóa bí mật của SP, SP phải khai báo nó ở đây để ký vào vào SAML request muốn gửi tới cho IdP.authn_requests_signed
là có muốn ký vào SAML request gửi tới IdP hay không? Ở bên phía IdP có thể không cần xác thực chữ ký của SP cho dù bên SP có ký hay không.want_assertions_signed
là có yêu cầu SAML Assertions được IdP ký không? Bên phía IdP có thể không cần ký vào SAML Assertions cho dù bên SP có yêu cầu hay không. Sẽ không có lỗi gì được báo dù bên SP yêu cầu IdP ký nhưng IdP không ký.
Bạn để ý trong hàm create
không lấy user bằng email được gửi về từ okta (IdP) mà ta muốn IdP gửi về một thuộc tính khác (LastName
trong đoạn code trên).
Để tạo certificate
và private_key
ở trên, bạn chạy câu lệnh dưới đây trong terminal:
Nó sẽ tạo ra cho bạn một cặp khóa public key key.crt
và private key p_key.pem
. Khóa sẽ có hạn là 365
ngày như mình chỉ định trong câu lệnh trên.
3.2. Tạo ứng dụng IdP trên okta.
Đầu tiên bạn cần làm là thay đổi giao diện trên okta từ Developer Console
thành Classic UI
thì mới tạo được app:
Chọn tab Applications
và chọn Add Application
:
Khi tạo App thì chọn Platform là Web và SAML 2.0:
Trong phần setting của App bạn chọn như sau:
Single sign on URL: là assertion_cosumer_service_url
trong cấu hình rails (xem giải thích ở phần trên).
Audience URI (SP Entity ID): là issuer
trong cấu hình rails.
Trong phần Attribute Statements (Optional), bạn điền Name là LastName
và Value là user.lastName
, đây chính là tên và giá trị mà bạn mong muốn IdP sẽ trả về cho SP ngoài giá trị mặc định là email (xem method create
trong Rails ở phần trên).
Chú ý là giá trị của Value phải luôn là user.{field}
, và chỉ lấy được các thuộc tính field
có sẵn của user
trong okta.
Click vào Show Advanced Settings
và thiết lập như sau:
Để cài đặt được phần này bạn phải hiểu được phần Cách hoạt động của SAML mình giải thích ở đầu. Một số cấu hình cần chú ý là:
Response: Bạn có muốn IdP ký điện tử vào response trả về cho SP không?
Assertion Signature: Bạn có muốn IdP ký điện tử vào SAML assertions nằm trong SAML response không?
Assertion Encryption: Bạn có muốn IdP mã hóa SAML assertions trả về cho SP không?
Encryption Certificate: Nếu bạn muốn IdP mã hóa SAML Assertion thì bạn phải chỉ định SP public key ở phía IdP. Đây chính là file public key key.cer
của SP bạn tạo ở trên, bạn upload file này lên okta.
Sau khi kết thúc cài đặt settings, bạn cần phải gán app vừa tạo cho một tài khoản thì mới request được từ SP của bạn tới IdP. Click vào tab Assignments
rồi chọn Assign to People
:
Ở tab Sign On
, bạn sẽ thấy các thông tin cần thiết của IdP để cấu hình trong SP của bạn:
Nếu bạn muốn các thông tin riêng biệt của IdP thì click vào View Setup Instructions
, còn nếu bạn chỉ muốn metadata url của IdP để SP của bạn có thể tự động lấy thông tin (như mình làm trong phần saml_settings trong rails ở trên) thì click vào Identity Provider metadata
để hiển thị thông tin metadata của IdP và lấy url của nó, phần cấu hình tự động lấy thông tin của IdP từ metadata chính là câu lệnh này trong rails:
Sau khi đã cài đặt SP và IdP xong thì bạn truy cập vào url http://localhost:3001/mrs/saml/sign_in
để test (mình dùng cổng 3001 cho rails app).
Link tham khảo:
https://en.wikipedia.org/wiki/SAML_Metadata
https://developer.okta.com/standards/SAML/setting_up_a_saml_application_in_okta/
0 Nhận xét