Golang实现Azure AD登录的授权码授权流程

Golang实现Azure AD登录的授权码授权流程 我想在Go语言中为一个应用程序实现授权码授权流程。该应用随后将读取用户有权访问的(委托)Azure资源。

我已经在GitHub和其他地方梳理了几十个示例,但它们要么不完整,要么没有按预期弹出登录提示。

我正在寻找一个纯粹使用REST(更佳)的示例。如果没有,使用adal/msal、"golang.org/x/oauth2/microsoft"或其他任何方法也可以。同时,我需要从请求中获取访问令牌,因为Azure的Go SDK并未覆盖所有资源,我希望使用该访问令牌进行REST调用。

enter image description here

任何指向有效代码示例的指引都将不胜感激。注意:我可以使用其他方法(如客户端凭据)成功登录。问题仅在于让授权码流程正常工作。

谢谢。


更多关于Golang实现Azure AD登录的授权码授权流程的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang实现Azure AD登录的授权码授权流程的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是一个使用 golang.org/x/oauth2 包实现 Azure AD 授权码授权流程的完整示例。该示例将引导用户完成登录流程,获取访问令牌,并使用该令牌调用 Microsoft Graph API 获取用户信息。

首先,确保在 Azure 门户中注册应用并配置重定向 URI(例如 http://localhost:8080/auth/callback),并授予 User.Read 权限(委托权限)。

1. 安装依赖

go get golang.org/x/oauth2

2. 主要代码实现

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/microsoft"
)

// 配置 OAuth2
var (
    oauthConfig = &oauth2.Config{
        ClientID:     "YOUR_CLIENT_ID", // 替换为你的客户端 ID
        ClientSecret: "YOUR_CLIENT_SECRET", // 替换为你的客户端密钥
        RedirectURL:  "http://localhost:8080/auth/callback",
        Scopes:       []string{"User.Read"},
        Endpoint:     microsoft.AzureADEndpoint("YOUR_TENANT_ID"), // 替换为你的租户 ID
    }
    state = "random-state-string" // 用于防止 CSRF 攻击
)

func main() {
    http.HandleFunc("/", handleHome)
    http.HandleFunc("/login", handleLogin)
    http.HandleFunc("/auth/callback", handleCallback)

    fmt.Println("服务器运行在 http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

// 主页
func handleHome(w http.ResponseWriter, r *http.Request) {
    html := `<html><body><a href="/login">使用 Azure AD 登录</a></body></html>`
    w.Write([]byte(html))
}

// 跳转到 Azure AD 登录页面
func handleLogin(w http.ResponseWriter, r *http.Request) {
    url := oauthConfig.AuthCodeURL(state, oauth2.AccessTypeOffline)
    http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

// 处理回调,获取访问令牌
func handleCallback(w http.ResponseWriter, r *http.Request) {
    if r.URL.Query().Get("state") != state {
        http.Error(w, "状态不匹配", http.StatusBadRequest)
        return
    }

    code := r.URL.Query().Get("code")
    token, err := oauthConfig.Exchange(context.Background(), code)
    if err != nil {
        http.Error(w, "无法交换令牌: "+err.Error(), http.StatusInternalServerError)
        return
    }

    // 使用访问令牌调用 Microsoft Graph API
    client := oauthConfig.Client(context.Background(), token)
    resp, err := client.Get("https://graph.microsoft.com/v1.0/me")
    if err != nil {
        http.Error(w, "请求 Graph API 失败: "+err.Error(), http.StatusInternalServerError)
        return
    }
    defer resp.Body.Close()

    // 读取响应(此处简化处理,实际应解析 JSON)
    w.Write([]byte("成功获取用户信息!访问令牌: " + token.AccessToken))
}

3. 使用访问令牌进行 REST 调用

获取访问令牌后,可以将其用于任何 Azure REST API 调用。以下示例演示如何将访问令牌添加到请求头中:

func callAzureResource(token *oauth2.Token, resourceURL string) {
    req, _ := http.NewRequest("GET", resourceURL, nil)
    req.Header.Set("Authorization", "Bearer "+token.AccessToken)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    // 处理响应...
}

4. 配置说明

  • YOUR_CLIENT_IDYOUR_CLIENT_SECRETYOUR_TENANT_ID 替换为你的 Azure 应用注册信息。
  • 确保重定向 URI 与 Azure 门户中配置的完全一致。
  • 根据需要调整 Scopes(例如 https://management.azure.com/user_impersonation 用于 Azure 资源管理)。

注意事项

  • 此示例使用内存存储,生产环境应使用安全存储(如数据库)管理令牌和状态。
  • 客户端密钥需保密,避免硬编码在代码中(可使用环境变量)。

运行程序后,访问 http://localhost:8080 并点击登录链接,将跳转到 Azure AD 登录页面。登录成功后,回调页面将显示访问令牌和用户信息。

回到顶部