Chuyển đến nội dung chính

Bài 12: Identity Brokering và Social Login

Identity Provider concept, cấu hình Social Login (Google, Facebook, GitHub, Apple, Microsoft), OpenID Connect Identity Providers, SAML Identity Providers, OAuth v2 providers, Kubernetes Identity Providers. First Login Flow, Account Linking, Identity Provider Mappers, Sync Mode (import, force, legacy), client-suggested IdP (kc_idp_hint) và IdP logout flow.

🔒 DevSecOps — Bài 12 Bài 12: Identity Brokering và Social Login

Keycloak từ Cơ bản đến Nâng cao

Phần 3: Authentication, MFA và Identity Brokering

xdev.asia

1. Identity Brokering — Khái niệm

Identity Brokering cho phép Keycloak đóng vai trò trung gian xác thực giữa ứng dụng và các Identity Providers (IdP) bên ngoài. Thay vì mỗi ứng dụng tự tích hợp với Google, Facebook, SAML IdP riêng, tất cả đều kết nối qua Keycloak.

┌──────────┐     ┌──────────────┐     ┌──────────────────┐
│  My App  │ ──→ │   Keycloak   │ ──→ │  External IdP    │
│          │ ←── │  (Broker)    │ ←── │  (Google, SAML)  │
└──────────┘     └──────────────┘     └──────────────────┘

Flow:
1. User truy cập My App → redirect đến Keycloak
2. User chọn "Login with Google" trên Keycloak login page
3. Keycloak redirect đến Google OAuth2
4. User xác thực tại Google → redirect về Keycloak
5. Keycloak nhận identity, tạo/link user, issue token
6. User redirect về My App với Keycloak token

Lợi ích:

  • Centralized: Cấu hình IdP 1 lần tại Keycloak, tất cả apps đều dùng được
  • Protocol bridging: App dùng OIDC, external IdP dùng SAML → Keycloak bridge
  • User management: Keycloak quản lý tập trung, kể cả users từ external IdP
  • Account linking: Link nhiều external identities vào 1 Keycloak account

2. Cấu hình Social Login

2.1 General Identity Provider Settings

Khi thêm bất kỳ IdP nào, các settings chung bao gồm:

SettingMô tảGiá trị
AliasIdentifier duy nhất cho IdP trong Keycloakgoogle, facebook
Display NameTên hiển thị trên login pageGoogle, Đăng nhập bằng Facebook
EnabledBật/tắt IdPOn
Hide on Login PageẨn khỏi login page (chỉ dùng qua kc_idp_hint)Off
Store TokensLưu access token từ external IdPOff (bật nếu cần gọi API external)
Stored Tokens ReadableUser có thể đọc stored tokensOff
Trust EmailTrust email từ IdP (không cần verify lại)On cho Google/Microsoft
Account Linking OnlyChỉ dùng để link account, không cho tạo mớiOff
First Login FlowFlow xử lý lần đầu đăng nhậpFirst Broker Login
Post Login FlowFlow chạy sau mỗi lần đăng nhập qua IdPNone
Sync ModeĐồng bộ user attributesimport, force, hoặc legacy

2.2 Google OAuth2

Bước 1: Tạo OAuth2 Credentials tại Google

  1. Truy cập Google Cloud Console → APIs & Services → Credentials
  2. Click "Create Credentials → OAuth Client ID"
  3. Application type: Web application
  4. Name: Keycloak Login
  5. Authorized redirect URIs: https://keycloak.example.com/realms/myrealm/broker/google/endpoint
  6. Copy Client ID và Client Secret

Bước 2: Cấu hình trong Keycloak

  1. Vào Identity Providers → Add provider → Google
  2. Nhập:
    • Client ID: 123456789.apps.googleusercontent.com
    • Client Secret: GOCSPX-xxxxxxxxxxxx
    • Default Scopes: openid profile email
    • Trust Email: On — Google đã verify email
    • Sync Mode: import
  3. Save

Redirect URI format:

https://{keycloak-host}/realms/{realm}/broker/{alias}/endpoint

2.3 Facebook

Bước 1: Tạo Facebook App

  1. Truy cập Meta for Developers → My Apps → Create App
  2. App type: Consumer hoặc Business
  3. Thêm product "Facebook Login"
  4. Settings:
    • Valid OAuth Redirect URIs: https://keycloak.example.com/realms/myrealm/broker/facebook/endpoint
  5. Copy App ID và App Secret

Bước 2: Cấu hình trong Keycloak

  1. Vào Identity Providers → Add provider → Facebook
  2. Nhập:
    • Client ID: App ID
    • Client Secret: App Secret
    • Default Scopes: email public_profile
    • Trust Email: Off — Facebook cho phép email chưa verify

2.4 GitHub

Bước 1: Tạo GitHub OAuth App

  1. Truy cập GitHub → Settings → Developer Settings → OAuth Apps → New
  2. Application name: Keycloak Login
  3. Homepage URL: https://myapp.example.com
  4. Authorization callback URL: https://keycloak.example.com/realms/myrealm/broker/github/endpoint
  5. Copy Client ID và generate Client Secret

Bước 2: Cấu hình trong Keycloak

  1. Vào Identity Providers → Add provider → GitHub
  2. Nhập:
    • Client ID: GitHub Client ID
    • Client Secret: GitHub Client Secret
    • Default Scopes: user:email read:org (thêm read:org nếu cần org info)

2.5 Apple Sign In

Bước 1: Cấu hình tại Apple Developer

  1. Truy cập Apple Developer → Certificates, Identifiers & Profiles
  2. Tạo App ID với Sign In with Apple capability
  3. Tạo Services ID:
    • Identifier: com.example.keycloak.login
    • Return URLs: https://keycloak.example.com/realms/myrealm/broker/apple/endpoint
  4. Tạo Key cho Sign In with Apple → download .p8 file

Bước 2: Cấu hình trong Keycloak

  1. Vào Identity Providers → Add provider → Apple
  2. Nhập:
    • Client ID: Services ID (com.example.keycloak.login)
    • Client Secret: Generated JWT từ .p8 key
    • Default Scopes: name email
    • Trust Email: On

⚠️ Lưu ý Apple: Apple yêu cầu Client Secret là JWT signed với .p8 key, và JWT này hết hạn sau 6 tháng. Bạn cần refresh Client Secret định kỳ hoặc sử dụng script tự động.

2.6 Microsoft (Azure AD / Entra ID)

Bước 1: Đăng ký App trong Azure

  1. Truy cập Azure Portal → Microsoft Entra ID → App registrations → New
  2. Name: Keycloak SSO
  3. Supported account types: chọn phù hợp
    • Accounts in this organizational directory only — Single tenant
    • Accounts in any organizational directory — Multi-tenant
    • Accounts in any organizational directory and personal — Bao gồm cả @outlook.com
  4. Redirect URI: Web → https://keycloak.example.com/realms/myrealm/broker/microsoft/endpoint
  5. Vào Certificates & secrets → New client secret → copy value

Bước 2: Cấu hình trong Keycloak

  1. Vào Identity Providers → Add provider → Microsoft
  2. Nhập:
    • Client ID: Application (client) ID
    • Client Secret: Client secret value
    • Default Scopes: openid profile email
    • Trust Email: On
    • Tenant: Nhập Tenant ID cho single-tenant, hoặc common cho multi-tenant

3. OpenID Connect Identity Providers

Ngoài social providers có sẵn, Keycloak hỗ trợ kết nối với bất kỳ OIDC provider nào.

3.1 Thêm OpenID Connect v1.0 Provider

  1. Vào Identity Providers → Add provider → OpenID Connect v1.0
  2. Cấu hình:
    • Alias: corporate-sso
    • Display Name: Corporate SSO
    • Discovery Endpoint: https://sso.corp.example.com/.well-known/openid-configuration
    • Hoặc nhập manual:
      • Authorization URL: https://sso.corp.example.com/authorize
      • Token URL: https://sso.corp.example.com/token
      • User Info URL: https://sso.corp.example.com/userinfo
      • JWKS URL: https://sso.corp.example.com/jwks
    • Client ID: ID đã đăng ký tại external IdP
    • Client Secret: Secret tương ứng
    • Client Authentication: Client secret sent as post hoặc Client secret sent as basic auth

Discovery Endpoint cho phép Keycloak tự động fetch tất cả URLs và capabilities của external IdP.

3.2 Keycloak-to-Keycloak Identity Brokering

Kết nối 2 Keycloak instances:

# Keycloak A (IdP) — Realm: company-a
Discovery: https://keycloak-a.example.com/realms/company-a/.well-known/openid-configuration

# Keycloak B (Broker) — Realm: main
# Thêm OIDC IdP với:
# - Discovery Endpoint: https://keycloak-a.example.com/realms/company-a/.well-known/openid-configuration
# - Client ID: registered in company-a realm
# - Client Secret: from company-a client

# Tại Keycloak A, tạo client cho Keycloak B:
# - Client ID: keycloak-b-broker
# - Valid Redirect URIs: https://keycloak-b.example.com/realms/main/broker/company-a/endpoint
# - Client Authentication: On
# - Standard Flow: Enabled

4. SAML 2.0 Identity Providers

4.1 Thêm SAML IdP

  1. Vào Identity Providers → Add provider → SAML v2.0
  2. Cấu hình:
    • Alias: corporate-saml
    • Import from URL: Nhập metadata URL của external SAML IdP
      https://saml-idp.example.com/metadata
    • Hoặc Import from file: Upload XML metadata file
    • Hoặc nhập manual:
      • Single Sign-On Service URL: https://saml-idp.example.com/sso
      • Single Logout Service URL: https://saml-idp.example.com/slo
      • NameID Policy Format: Email hoặc Persistent
      • Want AuthnRequests Signed: On
      • Want Assertions Signed: On
      • Want Assertions Encrypted: Off
      • Validate Signature: On
      • Validating X509 Certificates: Paste IdP signing certificate

4.2 Keycloak SAML SP Metadata

External SAML IdP cần metadata của Keycloak (acting as Service Provider):

# Keycloak SP Descriptor URL
https://keycloak.example.com/realms/myrealm/broker/corporate-saml/endpoint/descriptor

# Đây là XML metadata chứa:
# - EntityID
# - AssertionConsumerService URL
# - SingleLogoutService URL
# - Keycloak signing certificate

5. OAuth v2 Identity Providers

Cho các providers chỉ hỗ trợ OAuth 2.0 (không có OIDC):

  1. Vào Identity Providers → Add provider → OAuth v2.0
  2. Cấu hình:
    • Authorization URL: OAuth2 authorize endpoint
    • Token URL: OAuth2 token endpoint
    • User Info URL: Endpoint trả về user info (nếu có)
    • Client ID / Client Secret
    • User Info JSON Path: JSONPath để extract user attributes
      # Ví dụ: nếu user info response là { "data": { "id": 123, "username": "john" } }
      # Username JSONPath: $.data.username
      # Email JSONPath: $.data.email

6. Kubernetes Identity Providers

Keycloak có thể hoạt động như IdP cho Kubernetes, và ngược lại có thể nhận identity từ Kubernetes.

6.1 Kubernetes OpenID Connect Provider

# Kubernetes API server config — sử dụng Keycloak làm IdP
apiVersion: v1
kind: Config
clusters:
- cluster:
    server: https://k8s-api.example.com
    certificate-authority: /etc/kubernetes/pki/ca.crt
  name: my-cluster
users:
- name: oidc-user
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      command: kubectl
      args:
        - oidc-login
        - get-token
        - --oidc-issuer-url=https://keycloak.example.com/realms/myrealm
        - --oidc-client-id=kubernetes
        - --oidc-extra-scope=groups
# kube-apiserver flags cho OIDC authentication
--oidc-issuer-url=https://keycloak.example.com/realms/myrealm
--oidc-client-id=kubernetes
--oidc-username-claim=preferred_username
--oidc-groups-claim=groups
--oidc-ca-file=/etc/kubernetes/pki/keycloak-ca.crt

7. First Login Flow

First Login Flow xử lý lần đầu tiên user đăng nhập qua external IdP. Flow này quyết định:

  • Có tạo user mới trong Keycloak không?
  • Có link với user hiện tại không?
  • Có yêu cầu review/update profile không?

7.1 Default First Broker Login Flow

First Broker Login Flow (mặc định)
├── Review Profile (Required)                    → Hiển thị profile để user review
│   └── Config: Update Profile on First Login = missing
└── User Creation or Linking (Required)           → Sub-flow
    ├── Create User If Unique (Alternative)       → Tạo user nếu email/username chưa tồn tại
    └── Handle Existing Account (Alternative)     → Sub-flow xử lý account đã tồn tại
        ├── Confirm Link Existing Account (Required) → Hỏi user có muốn link?
        └── Verification (Alternative)            → Sub-flow verify ownership
            ├── Verify Existing Account by Email (Alternative) → Gửi email verify
            └── Verify Existing Account by Re-authentication (Alternative) → Nhập password

7.2 Cách hoạt động chi tiết

Scenario 1: User mới hoàn toàn

  1. User đăng nhập qua Google lần đầu
  2. Review Profile: Hiển thị profile (email, name) từ Google để user xác nhận
  3. Create User If Unique: Email chưa tồn tại → tạo Keycloak user mới
  4. Link Google identity với Keycloak user
  5. Đăng nhập thành công

Scenario 2: Email đã tồn tại trong Keycloak

  1. User đăng nhập qua GitHub, email [email protected]
  2. Create User If Unique: Email đã tồn tại → fail → chuyển sang alternative
  3. Confirm Link Existing Account: Hỏi "Account [email protected] đã tồn tại. Bạn muốn link?"
  4. Verify ownership: User verify bằng email HOẶC nhập password Keycloak
  5. Link GitHub identity với existing Keycloak user

7.3 Custom First Login Flow

Ví dụ: Auto-link account theo email không cần verify (chỉ dùng khi trust external IdP):

Auto-link First Login Flow
├── Create User If Unique (Alternative)
└── Automatically Set Existing User (Alternative)   ← Tự link, không hỏi user

⚠️ Cảnh báo bảo mật: Automatically Set Existing User chỉ nên dùng khi bạn hoàn toàn tin tưởng external IdP. Nếu IdP cho phép tự do đặt email, attacker có thể chiếm account bằng cách đăng ký email người khác.

8. Account Linking

Account Linking cho phép user liên kết nhiều external identities vào 1 Keycloak account.

8.1 Linking qua Account Console

User có thể tự link/unlink trong Account Console:

https://keycloak.example.com/realms/myrealm/account/#/security/linked-accounts

8.2 Linking qua Application Initiated Action (AIA)

# Trigger account linking từ application
GET /realms/myrealm/protocol/openid-connect/auth?
  client_id=my-app&
  redirect_uri=https://myapp.example.com/callback&
  response_type=code&
  scope=openid&
  kc_action=oidc-link&
  kc_action_parameter=google

8.3 Linking qua Admin REST API

# Xem federated identities của user
curl -s -X GET \
  "https://keycloak.example.com/admin/realms/myrealm/users/$USER_ID/federated-identity" \
  -H "Authorization: Bearer $ADMIN_TOKEN" | jq

# Response
[
  {
    "identityProvider": "google",
    "userId": "google-user-id-123",
    "userName": "[email protected]"
  }
]

# Thêm federated identity cho user
curl -X POST \
  "https://keycloak.example.com/admin/realms/myrealm/users/$USER_ID/federated-identity/github" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "identityProvider": "github",
    "userId": "github-user-id-456",
    "userName": "johndoe"
  }'

# Xóa federated identity
curl -X DELETE \
  "https://keycloak.example.com/admin/realms/myrealm/users/$USER_ID/federated-identity/github" \
  -H "Authorization: Bearer $ADMIN_TOKEN"

9. Identity Provider Mappers

IdP Mappers cho phép transform và map attributes từ external IdP sang Keycloak user attributes, roles, hoặc groups.

9.1 Mapper Types

MapperMô tảVí dụ
Attribute ImporterImport attribute từ IdP claim sang Keycloak user attributeIdP picture → Keycloak avatar_url
Hardcoded RoleGán role cố định cho tất cả users từ IdPTất cả Google users → role external-user
Hardcoded GroupGán group cố địnhTất cả GitHub users → group /external/github
Username Template ImporterTạo username từ template${ALIAS}.${CLAIM.preferred_username}
External Role to RoleMap external IdP role sang Keycloak roleSAML role admin → Keycloak role realm-admin
Hardcoded AttributeSet attribute cố định cho users từ IdPsource=google cho tất cả Google users
SAML Attribute to RoleMap SAML assertion attribute sang Keycloak roleSAML department=IT → role it-team
Advanced Claim to RoleMap claim phức tạp (JSON path, regex) sang roleClaim groups contains "admins" → role admin

9.2 Cấu hình Mappers

Ví dụ 1: Attribute Importer — Import avatar từ Google

  1. Vào Identity Providers → Google → Mappers → Add mapper
  2. Cấu hình:
    • Name: Import Avatar URL
    • Mapper Type: Attribute Importer
    • Claim: picture (claim name từ Google)
    • User Attribute Name: avatar_url (Keycloak user attribute)
    • Sync Mode Override: inherit

Ví dụ 2: Hardcoded Role — Gán role cho external users

  1. Vào Identity Providers → GitHub → Mappers → Add mapper
  2. Cấu hình:
    • Name: Assign External User Role
    • Mapper Type: Hardcoded Role
    • Role: external-user

Ví dụ 3: Username Template — Prefix username với IdP alias

  1. Cấu hình:
    • Mapper Type: Username Template Importer
    • Template: ${ALIAS}.${CLAIM.preferred_username}
    • Target: LOCAL
  2. Kết quả: user từ Google sẽ có username = google.john.doe

Ví dụ 4: External Role to Role — Map SAML roles

  1. Cấu hình:
    • Mapper Type: External Role to Role
    • External Role: admin (role name từ external SAML IdP)
    • Role: realm-admin (Keycloak role)

10. Sync Modes

Sync Mode kiểm soát cách Keycloak đồng bộ thông tin từ external IdP mỗi lần user đăng nhập.

ModeFirst LoginSubsequent LoginsUse case
importImport attributes từ IdPKhông cập nhật — giữ nguyên data KeycloakUser có thể chỉnh profile trong Keycloak
forceImport attributes từ IdPLuôn overwrite với data mới từ IdPIdP là source of truth tuyệt đối
legacyImport attributes từ IdPCập nhật nếu attribute trống, giữ nguyên nếu đã cóTương thích backward, merge data

Cấu hình Sync Mode:

  • Ở IdP level: Áp dụng cho tất cả mappers của IdP đó
  • Ở Mapper level (Sync Mode Override): Override sync mode cho mapper cụ thể
# Ví dụ: Google IdP với sync mode = import
# Mapper "Import Avatar" với Sync Mode Override = force

# Kết quả:
# - Email, name: import 1 lần, user có thể sửa trong Keycloak
# - Avatar URL: luôn cập nhật từ Google (force)

11. Client-suggested IdP (kc_idp_hint)

kc_idp_hint cho phép ứng dụng tự động redirect user đến external IdP cụ thể, bỏ qua Keycloak login page.

11.1 Sử dụng kc_idp_hint

# Redirect trực tiếp đến Google login
GET /realms/myrealm/protocol/openid-connect/auth?
  client_id=my-app&
  redirect_uri=https://myapp.example.com/callback&
  response_type=code&
  scope=openid&
  kc_idp_hint=google

# Redirect trực tiếp đến SAML IdP
GET /realms/myrealm/protocol/openid-connect/auth?
  client_id=my-app&
  redirect_uri=https://myapp.example.com/callback&
  response_type=code&
  scope=openid&
  kc_idp_hint=corporate-saml

JavaScript integration:

// keycloak-js adapter
const keycloak = new Keycloak({
  url: 'https://keycloak.example.com',
  realm: 'myrealm',
  clientId: 'my-app'
});

// Đăng nhập qua Google
function loginWithGoogle() {
  keycloak.login({
    idpHint: 'google'
  });
}

// Đăng nhập qua corporate SAML
function loginWithCorporate() {
  keycloak.login({
    idpHint: 'corporate-saml'
  });
}

11.2 Identity Provider Redirector trong Browser Flow

Identity Provider Redirector dalam Browser Flow tự động xử lý kc_idp_hint:

  • Nếu request có kc_idp_hint=google → redirect ngay đến Google
  • Nếu không có hint → tiếp tục flow bình thường (hiển thị login page)

Default IdP: Bạn có thể set default IdP cho Identity Provider Redirector — khi không có hint, tự redirect đến IdP mặc định:

  1. Click ⚙️ bên cạnh Identity Provider Redirector
  2. Nhập Default Identity Provider: google

12. Identity Broker Logout

Khi user logout khỏi Keycloak, bạn có thể cấu hình để propagate logout đến external IdP.

12.1 Backchannel Logout

Keycloak hỗ trợ backchannel logout với external OIDC IdP:

  1. Trong OIDC IdP configuration, enable Backchannel Logout
  2. External IdP phải hỗ trợ backchannel logout endpoint
  3. Khi user logout khỏi Keycloak → Keycloak gửi logout request đến external IdP

Cho SAML IdP, logout propagation được xử lý qua SAML Single Logout (SLO) protocol tự động.

13. Multiple Instances of Same Social Broker

Keycloak cho phép thêm nhiều instances của cùng một social provider, mỗi cái với alias khác nhau:

# Ví dụ: 2 Google IdPs cho 2 Google Workspace domains
Identity Providers:
  - Alias: google-corp        → Google Workspace domain corp.example.com
  - Alias: google-partner     → Google Workspace domain partner.example.com

# Mỗi instance có Client ID / Client Secret riêng
# registered tại Google Cloud Console khác nhau

Cách thêm:

  1. Thêm OIDC v1.0 provider (không dùng built-in Google provider cho instance thứ 2)
  2. Alias: google-partner
  3. Discovery Endpoint: https://accounts.google.com/.well-known/openid-configuration
  4. Client ID / Secret: credentials riêng cho instance thứ 2

14. Hiện/Ẩn IdPs trong Account Console

Kiểm soát user có thể thấy và link/unlink IdP nào trong Account Console:

  • Hiện trên Login page: Không tick Hide on Login Page
  • Ẩn khỏi Login page: Tick Hide on Login Page — vẫn dùng được qua kc_idp_hint
  • Hiện trong Account Console: IdP mặc định hiện trong Linked Accounts
  • Account Linking Only: IdP chỉ hiện trong Account Console, không hiện ở Login page

15. Tóm tắt

Khái niệmMô tả
Identity BrokeringKeycloak làm trung gian giữa apps và external IdPs
Social LoginGoogle, Facebook, GitHub, Apple, Microsoft
OIDC/SAML/OAuth2 IdPKết nối bất kỳ IdP nào theo protocol standards
First Login FlowXử lý lần đầu: tạo user mới hoặc link existing
Account LinkingLink nhiều external identities vào 1 Keycloak account
IdP MappersTransform attributes: Attribute Importer, Hardcoded Role/Group, Username Template
Sync Modesimport (1 lần), force (luôn overwrite), legacy (merge)
kc_idp_hintSkip login page, redirect thẳng đến IdP cụ thể
Broker LogoutPropagate logout đến external IdP (backchannel/SLO)