IAM(3)- IDaaS

 IDaaS(Identity as a Service)身份即服务其实就是IAM的云应用,本质上还是属于SaaS软件即服务的范畴,非严格意义上讲,它的前身就是本地组网里的LDAP/Active Directory目录服务器,而所谓的云化就是原本各个网络里的网络功能节点统一由更高层级网络里的平台节点提供,对于原本的网络而言,这些外移的服务节点就被云化了,在简单点来说就是自建还是依赖于公网服务提供商。

On-premises vs Cloud

在云时代云平台提供的各类云计算服务(SaaS,PaaS,IaaS)其实就是本地计算服务的外移聚合形式,由于本地环境和云环境的差异,这也导致了云下应用因为需求的不同导致的设计架构和理念的不同形式,云原生(Cloud Native)就是典型针对弹性和分布式需求的回应,其做法就是容器的自动化编排,此外在和其他服务交互上也会有各自的特点。

LDAP/AD

在众多企业级网络里可能微软的Active Directory是比较重要的IAM节点,作为IAM它主要就是记录Identity身份信息和Access权限信息,相应的对外提供服务也是基于身份信息比如用户ID和密码的Authentication认证服务,和基于权限信息的Authorization授权服务。

因为目录服务主要就是基于LDAP的目录树服务,所以身份信息主要就是用户和组的属性,认证方式就是传统的提供用户名和密码在服务端尝试binding,操作成功则返回认证成功,而权限信息就是成员属性,授权或者说鉴权方式就是通过获取的组成员属性里验证是否有所需要的组信息,查询成功则代表鉴权成功。

  • Identity - User, Group, etc (ldap item)
    • Authentication - 应用使用ID和passwd进行binding
  • Access  - memberOf (ldap item)
    • Authorization - 应用检查是否有组成员属性

所以这种传统的组网内,各个应用的服务端都会和IAM保持通信连接,通过用户的认证信息在IAM处换取用户的身份信息和权限信息,而客户端和服务端之间的会话session机制可以使得客户端在请求时携带本地存储的session cookie来让服务端复用之前获取的用户身份和权限信息,一般如果session过期服务端就要重新向IAM请求获取。

Cloud Based IAM

由于微软AD在大型企业组网内的流行,所以AD的云版本Microsoft Entra ID也顺势成为众多企业云化之后的IAM方案,和本地目录服务类似,云IAM会在不同组织的类别下记录Identity身份信息和Access权限信息,以及提供认证和鉴权服务。

  • Authorizatoin Code
    • Authentication - IAM Authorization Endpoint
  • Identity - ID (SAML XML, JWT ID Token)
    • Authorizatoin - IAM Token Endpoint
  • Access - Role, Scope (JWT Access Token, JWT Refresh Token)
    • Authorizatoin - IAM Token Endpoint

网络内的应用也是和IAM保持通信连接,通过用户的认证从IAM获取用户的身份信息和权限信息,但特点在于

  • 用户的认证服务和流程是由IAM的授权端点提供用于授权码的获取,即应用已经无需显式的登录页面
  • 应用从令牌端点获取身份信息形式为SAML XML或者JWT ID Token
  • 应用从令牌端点获取的权限信息形式为JWT Access Token,用于请求头中请求其他注册scope的应用服务
  • 应用还会从令牌端点获取JWT Refresh Token访问Token Endpoint用于所有Token重新请求,而无需请求授权端点

这些特点也主要是SAML, OAuth2.0 + OIDC协议的实现,其中SAML主要是基于XML Assertion的认证协议,而OAuth是基于JWT的授权协议,随后的OIDC算是从认证方面对OAuth的补全和拓展,两者构成了现在IAM认证加授权的全部内容。

OAuth2.0 Endpoint

下面是Microsoft Entra ID所以实现的OAuth2.0规范里的各类Endpoint 

Authorization Endpoint 授权端点

应用的服务端重定向客户端到授权端点,启动身份认证流程,用户可以使用不同方式的验证方法,验证成功后该端点返回授权码(Authorization Code)

一般通过重定向客户端到应用服务端授权码处理端点使得服务端获取到授权码,随后应用的服务端使用授权码通过Token端点获取Token

device_authorization_endpoint 设备授权端点

适用于没有前后端区分的应用,比如桌面应用和命令行应用,这种本地应用请求端点获取包含device_code,user_code,verification_uri的响应,用户需要使用其他设备访问verification_uri并输入user_code,随后进入身份认证流程,可以使用不同方式的验证方法

身份认证期间,本地应用会使用device_code轮询(polling)Token端点,如果用户身份认证完成,Token端点会返回令牌

Token Endpoint 令牌端点

应用的服务端在获取到授权码(Authorization Code)之后,传入授权码到令牌端点用于换取JWT令牌,一般包括全部的ID token(身份令牌), Access Token(访问令牌)和Refresh Token(刷新令牌)

应用的服务端可以使用刷新令牌(Refresh Token),通过令牌端点获取新的JWT令牌,一般包括全部三种令牌(Token)

End Session Endpoint 注销会话端点

应用的服务端重定向客户端到注销会话端点,注销客户端和IdP的会话session

Discovery Endpoint 元数据发现端点

OIDC(OpenID Connect)协议定义的元数据端点,用于自动发现包括上述所有的端点

OAuth2.0 Grant Flows

使用OAuth2.0的应用大体可以分为两类,一种是具备前后端的Condifential Client/APP,因为独立的后端可以确保信息的不泄露,一种是没有独立后端的前端应用,也即Public Client/APP,所有的流程都可用于有后端的应用,而前端应用仅适用于Authorization Code + PKCE和Device Code Flow这两种。

应用可以通过微软提供的Microsoft Authentication Library (MSAL)库来调用Microsoft Entra ID所实现的基于OAuth2.0协议的各类授权流程获取Token,一般可以分为三类

Redirect-based Flow 重定向机制

应用会重定向客户端浏览器到授权端点处理身份和授权流程并且通过重定向返回授权码

Authorizatoin Code Flow(授权码流程)

通过client_secret令牌端点表明应用的身份

  1. 请求:服务端发起重定向,附带 client_id, scope, redirect_uri。
  2. 登录/授权:用户在授权端点上登录,并同意授权。
  3. 授权码: 授权端点将临时的、一次性使用的授权码 (auth code) 重定向到 redirect_uri。
  4. 令牌交换: 服务端立即向令牌端点发起请求,使用 code 和私有的 client_secret 交换 ID Token, Access Token 和 Refresh Token。
from msal import ConfidentialClientApplication

app = ConfidentialClientApplication(
    client_id, authority=authority, client_credential=client_secret
)

# Step 1: Redirect user
auth_url = app.get_authorization_request_url(
    scopes=["User.Read"],
    redirect_uri=redirect_uri
)

# Step 2: Handle redirect and get the code
result = app.acquire_token_by_authorization_code(
    code,
    scopes=["User.Read"],
    redirect_uri=redirect_uri
)

Authorizatoin Code Flow with PKCE(PKCE 授权码流程)

通过PKCE机制生成一个密钥 code_verifier来替代client_secret向令牌端点表明应用的身份

  1. 密钥生成:应用生成 code_verifier (秘密) 和 code_challenge (公开发送)。
  2. 请求:应用将 code_challenge 附在授权请求中发送给授权端点。
  3. 登录和授权码: 用户在授权端点登录并统一授权,授权码返回到redirect_uri
  4. 令牌交换: 应用通过解析到授权码后,向令牌端点发送 auth code 和原始的 code_verifier。
  5. 验证: 授权端点用 code_verifier 重新计算code_challenge,并与步骤 2 中保存的挑战值比对,匹配成功令牌端点才发放令牌。
from msal import PublicClientApplication
import msal

app = PublicClientApplication(client_id, authority=authority)

# Step 1: Create PKCE
pkce = msal.Pkce()

auth_url = app.get_authorization_request_url(
    ["User.Read"],
    redirect_uri=redirect_uri,
    code_challenge=pkce.code_challenge,
    code_challenge_method="S256"
)

# Step 2: Use code_verifier to redeem token
result = app.acquire_token_by_authorization_code(
    code,
    ["User.Read"],
    redirect_uri=redirect_uri,
    code_verifier=pkce.code_verifier
)

Pooling-based Flow 轮询机制

适用于没有输入方式的应用,通过轮询令牌端点获取token

OAuth2.0 Device Code Flow(设备代码流程)

  1. 请求代码: 应用向 device_authorization_endpoint 请求 device_code、user_code(给用户看的短码)和 verification_uri。
  2. 用户授权: 用户在手机/电脑上访问 verification_uri,输入 user_code,并登录授权端点完成授权。
  3. 轮询: 应用周期性地(例如每 5 秒)向令牌端点发送 device_code 轮询 Token。
  4. 发放令牌: 一旦用户授权完成,Entra ID 响应的轮询请求中就会包含 Token。
from msal import PublicClientApplication

app = PublicClientApplication(client_id, authority=authority)

# Step 1: Acquire device code
flow = app.initiate_device_flow(scopes=["User.Read"])
print(flow["message"])  # inform user to login with other device

# Step 2: Poll the token endpoint
result = app.acquire_token_by_device_flow(flow)

Direct Request Flow 直接请求机制

应用的服务端直接和令牌端点进行通信获取令牌

Client Credentials Flow(客户端凭证流程)

  1. 直接请求: 服务端直接向令牌端点发起请求,请求体包含 grant_type=client_credentials、client_id、client_secret 和 scope。
  2. 验证/响应: 令牌端点验证应用凭证,确认其有权请求的 scope,然后直接返回Token。
from msal import ConfidentialClientApplication

app = ConfidentialClientApplication(
    client_id,
    authority=authority,
    client_credential=client_secret,
)

result = app.acquire_token_for_client(scopes=["/.default"])

Resource Owner Password Credentials Flow(资源所有者密码凭据流程)

已成为废弃流程,因为涉及到用户名和密码直接的传递,违背了认证仅在IdP的设计初衷

  1. 收集:应用获取用户名和密码。
  2. 直接提交:应用将用户名、密码、client_id 和(可选的)client_secret 直接发送给令牌端点。
  3. 认证/响应: 令牌端点认证凭据,并返回Token。
from msal import PublicClientApplication

app = PublicClientApplication(client_id, authority=authority)

result = app.acquire_token_by_username_password(
    username,
    password,
    scopes=["User.Read"]
)

OAuth2.0 + OIDC SSO

SSO实际上依赖于应用客户端和IdP以及客户端和服务端之间的会话机制,首先用户在本地成功登录IdP之后,IdP会和本地浏览器建立会话cookie,当另外一个应用的服务端重定向浏览器到IdP的时候,浏览器会携带留存的会话信息,IdP验证已登录的状态就会跳过认证流程直接返回授权码。

其次应用服务端获取到token之后也会在前端生成会话cookie,后续前端的请求中会自动携带会话信息,服务端可以通过这些信息检索到对应的token并解析使用,如果session或者cookie过期则会重新触发请求到IdP通过授权流程获取Token。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值