身份认证与授权(二):Okta、Auth0、AWS Cognito、ForgeRock、

身份认证与授权(一):SAML、OIDC之后,本文继续深入汇总介绍几个商业平台。

Okta

官网,全球领先的企业级IAM解决方案提供商,专注于为企业提供云端的身份验证、单点登录、多因素认证(MFA)、用户管理等服务。

核心产品线:

  1. Okta Workforce Identity(员工身份管理):
    • 单点登录到企业应用
    • MFA
    • 生命周期管理(用户入职/离职自动化)
    • 高级服务器访问(ASA),替代VPN的服务器访问方案
  2. Okta Customer Identity(客户身份管理,原Okta CIAM):
    • 面向外部用户的身份认证
    • 支持数百万用户规模
    • 自定义登录页面和品牌化
    • 社交登录和企业联合认证

架构:
#mermaid-svg-KnDQYUzEEOijtRL1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KnDQYUzEEOijtRL1 .error-icon{fill:#552222;}#mermaid-svg-KnDQYUzEEOijtRL1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KnDQYUzEEOijtRL1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KnDQYUzEEOijtRL1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KnDQYUzEEOijtRL1 .marker.cross{stroke:#333333;}#mermaid-svg-KnDQYUzEEOijtRL1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KnDQYUzEEOijtRL1 p{margin:0;}#mermaid-svg-KnDQYUzEEOijtRL1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 .cluster-label text{fill:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 .cluster-label span{color:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 .cluster-label span p{background-color:transparent;}#mermaid-svg-KnDQYUzEEOijtRL1 .label text,#mermaid-svg-KnDQYUzEEOijtRL1 span{fill:#333;color:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 .node rect,#mermaid-svg-KnDQYUzEEOijtRL1 .node circle,#mermaid-svg-KnDQYUzEEOijtRL1 .node ellipse,#mermaid-svg-KnDQYUzEEOijtRL1 .node polygon,#mermaid-svg-KnDQYUzEEOijtRL1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KnDQYUzEEOijtRL1 .rough-node .label text,#mermaid-svg-KnDQYUzEEOijtRL1 .node .label text,#mermaid-svg-KnDQYUzEEOijtRL1 .image-shape .label,#mermaid-svg-KnDQYUzEEOijtRL1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-KnDQYUzEEOijtRL1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KnDQYUzEEOijtRL1 .rough-node .label,#mermaid-svg-KnDQYUzEEOijtRL1 .node .label,#mermaid-svg-KnDQYUzEEOijtRL1 .image-shape .label,#mermaid-svg-KnDQYUzEEOijtRL1 .icon-shape .label{text-align:center;}#mermaid-svg-KnDQYUzEEOijtRL1 .node.clickable{cursor:pointer;}#mermaid-svg-KnDQYUzEEOijtRL1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KnDQYUzEEOijtRL1 .arrowheadPath{fill:#333333;}#mermaid-svg-KnDQYUzEEOijtRL1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KnDQYUzEEOijtRL1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KnDQYUzEEOijtRL1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KnDQYUzEEOijtRL1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KnDQYUzEEOijtRL1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KnDQYUzEEOijtRL1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KnDQYUzEEOijtRL1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KnDQYUzEEOijtRL1 .cluster text{fill:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 .cluster span{color:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KnDQYUzEEOijtRL1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KnDQYUzEEOijtRL1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-KnDQYUzEEOijtRL1 .icon-shape,#mermaid-svg-KnDQYUzEEOijtRL1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KnDQYUzEEOijtRL1 .icon-shape p,#mermaid-svg-KnDQYUzEEOijtRL1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KnDQYUzEEOijtRL1 .icon-shape .label rect,#mermaid-svg-KnDQYUzEEOijtRL1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KnDQYUzEEOijtRL1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KnDQYUzEEOijtRL1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KnDQYUzEEOijtRL1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 高可用
弹性扩展
安全隔离
集成
保护
API调用
事件推送
Okta云端服务
多区域部署

美国、欧盟、亚太
自动扩展架构
租户隔离

每个客户独立租户
企业客户
企业应用

如Salesforce、AWS、Office 365
开发者API

RESTful、GraphQL
事件钩子

用户变更实时通知

架构优势:

  1. 100%云端原生:
    • 无需部署本地服务器
    • 自动更新和维护
    • 99.99% SLA可用性保证
  2. 全球分布式架构:
    • 多数据中心部署
    • 自动故障转移
    • 数据驻留选项(美国、欧盟、加拿大、澳大利亚等)
  3. 安全性:
    • SOC 2 Type II、ISO 27001、ISO 27018认证,FedRAMP Moderate认证(美国政府)
    • 所有数据传输使用TLS 1.2+

全面支持现代身份认证标准:

协议/标准 支持情况 说明
OIDC 完整支持 作为IdP和SP,支持所有标准Flow
OAuth2.0 完整支持 支持所有授权模式,包括PKCE
SAML2.0 完整支持 作为IdP,支持SP-initiated和IdP-initiated
WS-Federation 支持 主要用于集成Microsoft生态系统
SCIM2.0 完整支持 自动化用户和组管理
LDAP 支持 通过Okta LDAP Agent集成
RADIUS 支持 用于VPN和Wi-Fi认证
FIDO2/WebAuthn 完整支持 无密码认证

提供丰富API和集成能力:

  1. REST API:
    • Users API:用户生命周期管理
    • Groups API:组和组成员管理
    • Apps API:应用分配和管理
    • Sessions API:会话管理
    • Logs API:审计日志查询
  2. SDK支持:
    • 前端:React、Vue、Angular、iOS、Android
    • 后端:Node.js、Java、Python、.NET、Go、PHP
  3. 预集成应用库:
    • 7k+预集成应用,如AWS、Salesforce、Slack、Office 365
    • 一键配置SSO
    • 自动化用户配置(Provisioning)

API调用示例:

js 复制代码
// 使用Okta Management API创建用户
const okta = require('@okta/okta-sdk-nodejs');
const client = new okta.Client({
  orgUrl: 'https://{your-okta-domain}.okta.com',
  token: 'API_TOKEN',
});
async function createUser() {
  const newUser = {
    profile: {
      firstName: 'Johnny',
      lastName: 'Wong',
      email: 'Johnny.Wong@awesome.com',
      login: 'Johnny.Wong@awesome.com',
    },
    credentials: {
      password: {
        value: 'SecurePassword123!',
      },
    },
  };
  try {
    const user = await client.createUser(newUser);
    console.log('用户创建成功:', user.id);
    // 分配用户到应用
    await client.assignUserToApplication('APP_ID', user.id, {
      scope: 'USER',
    });
    console.log('用户已分配到应用');
  } catch (err) {
    console.error('创建用户失败:', err);
  }
}
createUser();

OIDC配置示例(Okta作为IdP):

js 复制代码
// 使用 Okta OIDC 中间件(Node.js)
const { OktaAuth } = require('@okta/okta-auth-js');
const ExpressOIDC = require('@okta/okta-express-middleware');
const oidc = new ExpressOIDC({
  issuer: 'https://{your-okta-domain}.okta.com/oauth2/default',
  client_id: 'YOUR_CLIENT_ID',
  client_secret: 'YOUR_CLIENT_SECRET',
  appBaseUrl: 'http://localhost:3000',
  scope: 'openid profile email',
});
app.use(oidc.router);
// 受保护的路由
app.get('/dashboard', oidc.ensureAuthenticated(), (req, res) => {
  // req.userinfo 包含用户信息
  res.render('dashboard', { user: req.userinfo });
});

Auth0

官网,Identity As A Service提供商,可用于实现单点登录、无密码、MFA、社交网络认证、基于令牌的认证等,集成更改密码和忘记密码流程。官方文档

已被Okta收购,成为Okta旗下的开发者优先(Developer-First) 身份平台。

定位差异:

特性 Okta Auth0
目标用户 企业IT团队 开发者和产品团队
主要场景 Workforce Identity(员工) Customer Identity(客户)
定制灵活性 中等(低代码配置) 高(代码优先,规则引擎)
定价模式 按用户数 按MAU(月活跃用户)
开发者体验 良好 优秀(文档、QuickStart、社区)

协同效应:

  • Okta提供企业级IAM能力
  • Auth0提供开发者友好的B2C身份管理
  • 两者共享部分技术栈,但保持独立产品路线

核心优势:

  1. 规则引擎(Rules):
    • 使用JavaScript自定义认证流程
    • 在用户登录时动态修改Token和用户信息
    • 支持异步操作(如调用外部API)
  2. Hooks(钩子):
    • 在认证流程的特定节点执行自定义逻辑
    • 支持Node.js代码
    • 可用于审计、通知、数据同步等
  3. 自定义数据库连接:
    • 连接到现有用户数据库,如MySQL、MongoDB等
    • 无需迁移用户,平滑迁移到 Auth0
    • 支持自定义密码哈希验证
  4. 无密码认证:
    • 邮件链接登录
    • SMS/WhatsApp OTP
    • 生物识别:WebAuthn、FIDO2

实战

官方提供React、Angular、Next.js、iOS、Android、Java、.NET、Python等语言SDK。

Rules示例:

js 复制代码
// Auth0 Rule:在登录时调用外部 API 丰富用户信息
function enrichUserProfile(user, context, callback) {
  const axios = require('axios');
  // 仅对新用户执行
  if (context.stats.loginsCount > 1) {
    return callback(null, user, context);
  } 
  // 调用外部 API 获取用户积分
  axios.get(`https://api.awesome.com/users/${user.user_id}/points`)
    .then(response => {
      const points = response.data.points;
      // 将积分信息添加到 ID Token
      context.idToken['https://awesome.com/points'] = points;
      // 根据用户积分设置角色
      if (points > 1000) {
        context.idToken['https://awesome.com/role'] = 'vip';
      }
      callback(null, user, context);
    })
    .catch(err => {
      console.log('调用 API 失败:', err);
      callback(null, user, context);  // 不影响登录流程
    });
}

Hooks示例:

js 复制代码
// Auth0 Hook:用户注册后发送欢迎邮件
module.exports = function (user, context, cb) {
  const sendgrid = require('@sendgrid/mail');
  sendgrid.setApiKey(context.wehook.secrets.SENDGRID_API_KEY);
  const msg = {
    to: user.email,
    from: 'welcome@awesome.com',
    subject: '欢迎加入我们的平台!',
    html: `
      <h1>欢迎,${user.name}!</h1>
      <p>感谢您注册我们的服务。立即开始探索:</p>
      <a href="https://awesome.com/dashboard">前往控制台</a>
    `,
  };
  sendgrid.send(msg)
    .then(() => {
      console.log('欢迎邮件已发送');
      cb(null, { user, context });
    })
    .catch(err => {
      console.error('发送邮件失败:', err);
      cb(null, { user, context });  // 不阻止注册流程
    });
};

场景:使用Auth0保护React SPA和Node.js API

  1. React前端配置:
js 复制代码
// React 应用:使用 @auth0/auth0-react
import { Auth0Provider } from '@auth0/auth0-react';
import { useAuth0 } from '@auth0/auth0-react';

function App() {
  return (
    <Auth0Provider
      domain="YOUR_TENANT.auth0.com"
      clientId="CLIENT_ID"
      authorizationParams={{
        redirect_uri: window.location.origin,
        audience: "https://api.awesome.com",  // API Identifier
        scope: "openid profile email read:data",
      }}
    >
      <Router>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/dashboard" element={<ProtectedDashboard />} />
        </Routes>
      </Router>
    </Auth0Provider>
  );
}
// 受保护的组件
function ProtectedDashboard() {
  const { isAuthenticated, getAccessTokenSilently } = useAuth0();
  const [data, setData] = useState(null);
  useEffect(() => {
    if (isAuthenticated) {
      // 调用受保护的API
      getAccessTokenSilently()
        .then(token => {
          return fetch('https://api.awesome.com/data', {
            headers: {
              Authorization: `Bearer ${token}`,
            },
          });
        })
        .then(res => res.json())
        .then(data => setData(data));
    }
  }, [isAuthenticated, getAccessTokenSilently]);
  return <div>Dashboard: {JSON.stringify(data)}</div>;
}
  1. Node.jsAPI配置:
js 复制代码
// Node.js Express API:使用 express-oauth2-jwt-bearer
const { auth } = require('express-oauth2-jwt-bearer');
const express = require('express');
const app = express();
// 1. 验证 Auth0 Access Token
const checkJwt = auth({
  audience: 'https://api.awesome.com',  // 必须与前端的 audience 匹配
  issuerBaseURL: `https://YOUR_TENANT.auth0.com/`,
});
// 2. 受保护的路由
app.get('/data', checkJwt, (req, res) => {
  // req.auth包含解码后的Access Token信息
  const userId = req.auth.sub;
  const permissions = req.auth.permissions;  // 需配置API Authorization
  res.json({
    message: '这是受保护的数据',
    userId: userId,
    permissions: permissions,
  });
});
// 3. 基于权限的访问控制(RBAC)
const checkPermission = (requiredPermission) => {
  return (req, res, next) => {
    const userPermissions = req.auth.permissions || [];
    if (!userPermissions.includes(requiredPermission)) {
      return res.status(403).json({ error: '权限不足' });
    }  
    next();
  };
};
app.post('/data', checkJwt, checkPermission('write:data'), (req, res) => {
  // 仅允许有 write:data 权限的用户
  res.json({ message: '数据已创建' });
});
app.listen(3000, () => console.log('API运行在端口3000'));

AWS Cognito

Amazon Cognito是AWS提供的身份认证和访问控制服务,专为移动和Web应用设计。

核心组件:

  1. User Pools(用户池):
    • 作用:用户目录,提供注册、登录、配置文件管理功能
    • 支持的协议:OIDC、OAuth 2.0
    • Token类型:ID Token(JWT)、Access Token、Refresh Token
    • 用户存储:Cognito托管,自动扩展至数百万用户
  2. Identity Pools(身份池,原Federated Identities):
    • 作用:提供临时AWS凭证,用于访问AWS资源,如S3等
    • 身份来源:
      • 已认证用户:通过User Pool或第三方IdP
      • 未认证用户:Guest Access
    • 凭证类型:临时AWS IAM凭证(STS)

对比:

特性 用户池 身份池
主要目的 用户身份认证 AWS资源访问授权
返回内容 JWT Token(IDToken、AccessToken) 临时AWS凭证(AccessKey、SecretKey、SessionToken)
适用场景 应用登录、用户信息管理 访问S3桶、调用API Gateway、读写DynamoDB
用户存储 Cognito托管 不存储用户,仅颁发凭证
协议支持 OIDC、OAuth2.0、SAML2.0 AWS STS、OIDC(通过用户池交换)

集成架构:
AWS资源 身份池 用户池 应用 用户 AWS资源 身份池 用户池 应用 用户 #mermaid-svg-Z8cWIA4IcQgi95H4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Z8cWIA4IcQgi95H4 .error-icon{fill:#552222;}#mermaid-svg-Z8cWIA4IcQgi95H4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Z8cWIA4IcQgi95H4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Z8cWIA4IcQgi95H4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Z8cWIA4IcQgi95H4 .marker.cross{stroke:#333333;}#mermaid-svg-Z8cWIA4IcQgi95H4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Z8cWIA4IcQgi95H4 p{margin:0;}#mermaid-svg-Z8cWIA4IcQgi95H4 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Z8cWIA4IcQgi95H4 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Z8cWIA4IcQgi95H4 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Z8cWIA4IcQgi95H4 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Z8cWIA4IcQgi95H4 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Z8cWIA4IcQgi95H4 .sequenceNumber{fill:white;}#mermaid-svg-Z8cWIA4IcQgi95H4 #sequencenumber{fill:#333;}#mermaid-svg-Z8cWIA4IcQgi95H4 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Z8cWIA4IcQgi95H4 .messageText{fill:#333;stroke:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Z8cWIA4IcQgi95H4 .labelText,#mermaid-svg-Z8cWIA4IcQgi95H4 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .loopText,#mermaid-svg-Z8cWIA4IcQgi95H4 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Z8cWIA4IcQgi95H4 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Z8cWIA4IcQgi95H4 .noteText,#mermaid-svg-Z8cWIA4IcQgi95H4 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Z8cWIA4IcQgi95H4 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Z8cWIA4IcQgi95H4 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Z8cWIA4IcQgi95H4 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Z8cWIA4IcQgi95H4 .actorPopupMenu{position:absolute;}#mermaid-svg-Z8cWIA4IcQgi95H4 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Z8cWIA4IcQgi95H4 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Z8cWIA4IcQgi95H4 .actor-man circle,#mermaid-svg-Z8cWIA4IcQgi95H4 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Z8cWIA4IcQgi95H4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 1. 登录请求 2. 认证请求 3. 验证凭据 4. 返回ID Token + Access Token 5. 交换AWS凭证 (携带ID Token) 6. 验证Token,颁发IAM角色 7. 返回临时AWS凭证 8. 使用AWS凭证访问资源 9. 返回数据

与AWS服务的深度集成:

  1. Amazon API Gateway:
    • 使用Cognito User Pool Authorizer保护API
    • 自动验证JWT Token
    • 支持自定义Scopes进行细粒度授权
  2. AWS Amplify:
    -前端库(React、Vue、Angular、React Native)
    • 自动配置用户池和身份池
    • 提供认证UI组件(Amplify UI)
  3. AWS Lambda:
    • 触发器(Triggers):在用户注册、登录、忘记密码等事件时触发Lambda
    • 自定义认证流程:使用Lambda实现自定义Challenge-Response认证
  4. Amazon S3:
    • 使用身份池获取临时凭证
    • 基于IAM策略实现细粒度的S3桶访问控制

局限性:

  1. 自定义UI受限:
    • 托管UI自定义能力有限
    • 需要使用Amplify UI或自定义登录页面
  2. Lambda 触发器调试困难:
    • 错误信息不够详细
    • 需使用CloudWatch Logs调试
  3. 用户迁移复杂:
    • 不支持直接导入密码哈希
    • 需要使用"Migration Lambda"在用户首次登录时迁移
  4. Group数量限制:
    • 每个用户池最多1w个组
    • 每个用户最多100个组

实战

API Gateway集成Cognito示例:

js 复制代码
// AWS CDK定义:API Gateway使用Cognito授权
import * as cdk from 'aws-cdk-lib';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as cognito from 'aws-cdk-lib/aws-cognito';

const userPool = new cognito.UserPool(this, 'MyUserPool', {
  userPoolName: 'my-app-user-pool',
  selfSignUpEnabled: true,
  signInAliases: {
    email: true,
  },
});

const userPoolClient = new cognito.UserPoolClient(this, 'MyUserPoolClient', {
  userPool: userPool,
  oAuth: {
    flows: {
      authorizatonCodeGrant: true,
    },
    scopes: [cognito.OAuthScope.OPENID, cognito.OAuthScope.EMAIL],
  },
});

// API Gateway 使用 Cognito 授权
const api = new apigateway.RestApi(this, 'MyApi', {
  restApiName: 'My Protected API',
});

const authorizer = new apigateway.CognitoUserPoolsAuthorizer(this, 'MyAuthorizer', {
  cognitoUserPools: [userPool],
});

const protectedResource = api.root.addResource('protected');
protectedResource.addMethod('GET', new apigateway.MockIntegration(), {
  authorizer: authorizer,
  authorizationType: apigateway.AuthorizationType.COGNITO,
});

Cognito支持通过Lambda触发器自定义认证流程:

可用Lambda触发器:

触发器 触发时机 用途
Pre Sign-up 用户注册前 自动确认用户、拒绝特定邮箱域名
Post Confirmation 用户确认邮箱后 发送欢迎邮件、添加用户到数据库
Pre Authentication 用户登录前 实施自定义验证规则(如IP黑名单)
Post Authentication 用户登录后 记录登录日志、触发MFA
Custom Message 发送验证邮件/短信前 自定义邮件/短信内容
Forgot Password 用户忘记密码 自定义密码重置逻辑

自定义认证流程示例(使用挑战-响应):

js 复制代码
// Lambda 触发器:定义自定义认证挑战
exports.handler = async (event) => {
  if (event.triggerSource === 'DefineAuthChallenge') {
    // 检查用户是否已通过所有挑战
    if (event.request.session.length === 0) {
      // 第一个挑战:输入 OTP
      event.response.issueTokens = false;
      event.response.failAuthentication = false;
      event.response.challengeName = 'CUSTOM_CHALLENGE';
    } else if (event.request.session[0].challengeName === 'CUSTOM_CHALLENGE' &&
               event.request.session[0].challengeResult === true) {
      // 用户已通过 OTP 验证
      event.response.issueTokens = true;
      event.response.failAuthentication = false;
    } else {
      // 验证失败
      event.response.issueTokens = false;
      event.response.failAuthentication = true;
    }
  }
  return event;
};

// Lambda 触发器:创建自定义挑战(发送 OTP)
exports.handler = async (event) => {
  if (event.triggerSource === 'CreateAuthChallenge') {
    const otp = Math.floor(100000 + Math.random() * 900000);  // 6位 OTP
    
    // 将 OTP 存储到 Redis(用于后续验证)
    await redis.setex(`otp:${event.request.userName}`, 300, otp);
    
    // 发送 OTP 到用户手机(使用 Amazon SNS)
    await sns.publish({
      Message: `您的验证码是:${otp},5分钟内有效。`,
      PhoneNumber: event.request.userAttributes.phone_number,
    }).promise();
    
    // 将 OTP 返回给客户端(用于验证)
    event.response.publicChallengeParameters = {
      phone: event.request.userAttributes.phone_number,
    };
    event.response.privateChallengeParameters = {
      otp: otp.toString(),
    };
  }
  return event;
};

// Lambda触发器:验证自定义挑战
exports.handler = async (event) => {
  if (event.triggerSource === 'VerifyAuthChallengeResponse') {
    const expectedOtp = await redis.get(`otp:${event.request.userName}`);
    const providedOtp = event.request.challengeAnswer;
    
    if (expectedOtp === providedOtp) {
      event.response.answerCorrect = true;
      await redis.del(`otp:${event.request.userName}`);
    } else {
      event.response.answerCorrect = false;
    }
  }
  return event;
};

最佳实践:

  1. 使用Amplify客户端库:自动处理Token刷新、提供现成的UI组件
  2. 为生产环境启用MFA:如TOTP(Google Authenticator),或使用SMS/Email OTP
  3. 使用自定义域名:避免使用默认的*.auth.region.amazoncognito.com域名,提升品牌形象和用户信任
  4. 设置Token有效期:Access Token推荐5-60分钟、Refresh Token推荐1-365天、根据应用安全需求调整
  5. 使用App Client Secret:
    • 对于服务器端应用,启用App Client Secret
    • 对于 SPA 和移动应用,不要启用(无法安全存储Secret)

不推荐做法:

  1. 不要将敏感信息存储在ID Token中:ID Token能被客户端解码,使用Access Token或调用/userinfo端点
  2. Cognito是用于认证,认证成功后将用户配置文件存储在外部数据库如DynamoDB
  3. 不要在Lambda触发器中执行长时间操作:Lambda触发器有超时限制(默认5秒),长时间操作应使用异步方式,如SQS

成本优化建议:

  • 用户池:免费层(5w MAU),之后$0.0055/MAU
  • 身份池:免费(仅收取AWS资源使用费用)
  • 优化建议:
    • 使用Refresh Token减少Token刷新频率
    • 对于Guest Access,使用未经身份验证的角色(控制权限)
    • 监控MAU数量,避免不必要的活跃用户

ForgeRock

提供完整的身份平台,涵盖IAM、IGA、CIAM和MFA等;已被 Ping Identity收购,其技术平台与产品已整合进后者的身份管理平台,形成更全面的混合云身份和IAM解决方案。

开源项目主页能看到其核心产品矩阵:

  1. Access Management(AM):
    • 认证和授权服务器
    • 支持OIDC、OAuth 2.0、SAML 2.0
    • 策略决策点(PDP)和政策执行点(PEP)
  2. Identity Management(IDM):
    -用户生命周期管理
    • 工作流和审批流程
    • 连接器框架(连接到LDAP、AD、数据库等)
  3. Directory Services(DJ):
    • 基于Java开发、高性能LDAP和REST目录服务
    • 支持多主复制(Multi-master Replication)
    • 适用于大规模用户存储
  4. Identity Gateway(IG):
    • 反向代理和策略执行点
    • 保护遗留应用(无需修改代码)
    • 支持WebSocket和微服务

踩坑注意:这四个产品都有对应的,基于Java语言开发,开源社区版本,但已不再维护。

特色功能:

  • IoT身份认证:支持设备认证和授权
  • 隐私和同意管理:符合GDPR的用户同意管理
  • AI驱动的安全:使用机器学习检测异常行为

适用场景:

  • 电信运营商(需要管理数百万用户)
  • IoT平台(需要设备身份认证)
  • 需要隐私合规的企业(如GDPR、CCPA)

IBM Security Verify

IBM云原生身份即服务(IDaaS)平台,整合IAM和CIAM能力。