• home > tools > cloudServices > Azure >

    Microsoft Entra(Azure ADD) MSAL库SSO OAuth2登录详解

    Author:zhoulujun Date:

    《Microsoft 标识平台身份验证库 (MSAL) 使用:react+MsalProvider鉴权》 使用起来比较简单,但是交互流程是怎么样的呢?Microsoft 标

    Microsoft 标识平台身份验证库 (MSAL) 使用:react+MsalProvider鉴权》 使用起来比较简单,但是交互流程是怎么样的呢?


    Microsoft 标识平台支持各种新式应用体系结构的身份验证,所有这些体系结构都基于行业标准协议 OAuth 2.0 或 OpenID Connect

    这里安利下:《单点登录之身份验证与授权:CAS/OAuth/SAML/OpenID

    单页应用

    单页应用 (SPA) 前端, Microsoft 标识平台支持这些应用的方式是使用 OpenID Connect 协议进行身份验证,以及使用 OAuth 2.0 定义的两种授权类型之一。

     再安利下《OAuth 2.0 扩展协议之PKCE

    OAuth 2.0交互流程如下

    分为三个步骤:

    1. 请求授权代码(获取code)

    2. 兑换访问令牌的代码(通过code换取accessToken)

    3. 使用访问令牌获取用户信息(校验token并获取用户信息,并获取登陆用户信息)

    具体教程如下:https://learn.microsoft.com/zh-cn/entra/identity-platform/v2-oauth2-auth-code-flow#refresh-the-access-token

    该图显示了 OAuth 授权代码流。本机应用和 Web API 使用本文中描述的令牌进行交互。

    请求授权代码:/oauth2/v2.0/authorize 

    https://login.microsoftonline.com/common/oauth2/v2.0/authorize

    重定向进入登录页:重定向页面接口,跳转P10登陆窗口,并回调code给 业务

    https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
    client_id=00001111-aaaa-2222-bbbb-3333cccc4444
    &response_type=code
    &redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
    &response_mode=query
    &scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
    &state=12345
    &code_challenge=YTFjNjI1OWYzMzA3MTI4ZDY2Njg5M2RkNmVjNDE5YmEyZGRhOGYyM2IzNjdmZWFhMTQ1ODg3NDcxY2Nl
    &code_challenge_method=S256

    用户经过身份验证并授予同意后,Microsoft 标识平台将使用 response_mode 参数中指定的方法,将响应返回到位于所指示的 redirect_uri 的应用。

    GET http://localhost?
    code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...
    &state=12345

    发现已经存在登陆态,通过接口https://login.microsoftonline.com/kmsi  返回302重定向返回code

    参数说明:
    参数选择说明
    tenant必需请求路径中的 {tenant} 值可用于控制哪些用户可以登录应用程序。 有效值为 common、organizations、consumers 和租户标识符。 对于用户从一个租户登录到另一个租户的来宾场景,必须提供租户标识符才能让其登录到资源租户。 有关详细信息,请参阅终结点
    client_id必答Microsoft Entra 管理中心 - 应用注册体验分配给应用的“应用程序(客户端) ID”。
    response_type必答必须包括授权代码流的 code 。 如果使用混合流,则还可以包括 id_token 或 token。
    redirect_uri必需应用的 redirect_uri,你的应用可通过该应用发送和接收身份验证响应。 其必须完全符合在 Microsoft Entra 管理中心中注册的其中一个重定向 URI,否则必须是编码的 URL。 对于本机应用和移动应用,请使用一个建议的值:https://login.microsoftonline.com/common/oauth2/nativeclient(适用于使用嵌入式浏览器的应用)或 http://localhost(适用于使用系统浏览器的应用)。
    scope必需希望用户同意的范围的空格分隔列表。  对于请求的 /authorize 分支,此参数可以涵盖多个资源。 此值允许应用获取你要调用的多个 Web API 的同意。
    response_mode建议指定标识平台应如何将请求的令牌返回到应用。

    支持的值:

    - query:请求访问令牌时的默认值。 在重定向 URI 上提供代码作为查询字符串参数。 使用隐式流请求 ID 令牌时不支持该 query 参数。
    - fragment:通过使用隐式流请求 ID 令牌时的默认值。 如果只请求一个代码,也支持。
    - form_post:对重定向 URI 执行包含代码的 POST。 请求代码时支持。

    state建议同时随令牌响应返回的请求中所包含的值。 可以是想要的任何内容的字符串。 随机生成的唯一值通常用于 防止跨站点请求伪造攻击。 该值还可用于在身份验证请求发生前,对有关用户在应用中的状态信息进行编码。 例如,它可以对用户所在的页面或视图进行编码。
    prompt可选表示需要的用户交互类型。 有效值为 login、none、consent 和 select_account。

    - prompt=login 强制用户在该请求上输入其凭据,从而使单一登录无效。
    - prompt=none 则相反。 它确保不向用户显示任何交互式提示。 如果请求无法通过单一登录以无提示方式完成,则 Microsoft 标识平台将返回 interaction_required 错误。
    - prompt=consent 在用户登录后触发 OAuth 同意对话框,要求用户向应用授予权限。
    - prompt=select_account 将中断单一登录,提供帐户选择体验,列出会话或任何记住的帐户中的所有帐户,或者提供选择一起使用其他帐户的选项。
    login_hint可选可使用此参数预先填充用户登录页面的用户名和电子邮件地址字段。 应用在已经从前次登录提取 login_hint 可选声明后,可在重新身份验证时使用此参数。
    domain_hint可选如果包含,应用将跳过用户在登录页面上经历的基于电子邮件的发现过程,导致稍微更加流畅的用户体验。 例如,将其发送到其联合标识提供者。 应用可以在重新身份验证期间使用此参数,方法是从前次登录提取 tid。
    code_challenge建议/必需用于通过“用于代码交换的证明密钥”(PKCE) 来保护授权代码授予。 如果包含 code_challenge_method,则需要。 有关详细信息,请参阅 PKCE RFC。 目前建议将参数用于所有应用程序类型(公共和机密客户端),Microsoft 标识平台则要求使用授权代码流的单页应用使用此参数。
    code_challenge_method建议/必需用于为 code_challenge 参数编码 code_verifier 的方法。 此方法应为 S256,但是如果客户端不能支持 SHA256,则该规范允许使用 plain。

    如果已排除在外,且包含了 code_challenge,则假定 code_challenge 为纯文本。 Microsoft 标识平台支持 plain 和 S256。 有关详细信息,请参阅 PKCE RFC。 使用授权代码流的单页应用需要此参数。

    此时,系统会要求用户输入凭据并完成身份验证。 Microsoft 标识平台还将确保用户已同意 scope 查询参数中指定的权限。 如果用户未同意其中的任一权限,就让用户同意所需的权限。 有关详细信息,请参阅 Microsoft 标识平台中的权限和同意

    兑换访问令牌的代码:/oauth2/v2.0/token

    https://login.microsoftonline.com/common/oauth2/v2.0/token

    通过code换取accessToken:

    POST /{tenant}/oauth2/v2.0/token HTTP/1.1
    Host: https://login.microsoftonline.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=11112222-bbbb-3333-cccc-4444dddd5555
    &scope=https%3A%2F%2Fgraph.microsoft.com%2Fmail.read
    &code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
    &redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
    &grant_type=authorization_code
    &code_verifier=ThisIsntRandomButItNeedsToBe43CharactersLong 
    &client_secret=sampleCredentia1s

    获取 authorization_code 并获取用户授予的权限后,接下来可以兑换 code 以获取资源的 access_token。 通过向 /token 终结点发送 POST 请求来兑换 code

    参数说明:
    参数必需/可选说明
    tenant必需请求路径中的 {tenant} 值可用于控制哪些用户可以登录应用程序。 有效值为 commonorganizationsconsumers 和租户标识符。 有关详细信息,请参阅终结点
    client_id必答Microsoft Entra 管理中心 - 应用注册页分配给你的应用的应用程序(客户端)ID。
    scope可选范围的空格分隔列表。 范围必须全部来自单个资源,以及 OIDC范围(profileopenidemail)。 有关详细信息,请参阅 Microsoft 标识平台中的权限和同意。 此参数是授权代码流的 Microsoft 扩展,旨在允许应用在令牌兑换期间声明其需要令牌的资源。
    code必需的在流的第一个阶段获取的 authorization_code
    redirect_uri必需的用于获取 authorization_code 的相同 redirect_uri 值。
    grant_type必需必须是授权代码流的 authorization_code 。
    code_verifier建议用于获取 authorization_code 的相同 code_verifier。 如果在授权码授权请求中使用 PKCE,则需要。 有关详细信息,请参阅 PKCE RFC
    client_secret机密 Web 应用所需在应用注册门户中为应用创建的应用程序机密。 请不要在本机应用或单页应用中使用应用程序机密,因为 client_secret 无法可靠地存储在设备或网页上。 可将 client_secret 安全地存储在服务器端的 Web 应用和 Web API 需要应用程序机密。 与此处讨论的所有参数一样,客户端机密在发送之前必须进行 URL 编码。 此步骤由 SDK 完成。 有关 URI 编码的详细信息,请参阅 URI 常规语法规范。 还支持根据 RFC 6749 在授权标头中提供凭据的基本身份验证模式。


    获取用户信息

    https://graph.microsoft.com/v1.0/me

    通过accessToken获取登陆用户信息,并校验accessToken有效性

    import requests
    user_info_url = "https://graph.microsoft.com/v1.0/me"
    headers = {'Authorization': f'Bearer {access_token}'}
    user_info_response = requests.get(user_info_url, headers=headers)
    user_info = user_info_response.json()
    
    print(user_info)


    完整流程

    const axios = require('axios');  
    const querystring = require('querystring');  
      
    // 替换以下占位符为你的实际值  
    const tenantId = '{tenant-id}';  
    const clientId = '{client-id}';  
    const clientSecret = '{client-secret}';  
    const redirectUri = '{redirect-uri}';  
    const authorizationCode = '{authorization-code}';  
      
    // Step 2: Exchange authorization code for tokens  
    const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;  
    const tokenPayload = querystring.stringify({  
        grant_type: 'authorization_code',  
        client_id: clientId,  
        redirect_uri: redirectUri,  
        code: authorizationCode,  
        client_secret: clientSecret,  
    });  
      
    axios.post(tokenUrl, tokenPayload, {  
        headers: {  
            'Content-Type': 'application/x-www-form-urlencoded',  
        },  
    })  
    .then(tokenResponse => {  
        const accessToken = tokenResponse.data.access_token;  
      
        // Step 3: Get user info using the access token  
        const graphUrl = 'https://graph.microsoft.com/v1.0/me';  
        const config = {  
            headers: {  
                Authorization: `Bearer ${accessToken}`,  
            },  
        };  
      
        return axios.get(graphUrl, config);  
    })  
    .then(userInfoResponse => {  
        console.log(JSON.stringify(userInfoResponse.data, null, 2));  
    })  
    .catch(error => {  
        console.error('Error:', error);  
    });



    转载本站文章《Microsoft Entra(Azure ADD) MSAL库SSO OAuth2登录详解》,
    请注明出处:https://www.zhoulujun.cn/html/tools/cloudServices/Azure/9290.html