このガイドでは、Azure Identity SDK API を使用して、GitHub Copilot SDK を使用して Microsoft Foundry モデルで認証する方法について説明します。 ほとんどの言語ではDefaultAzureCredentialを使用します。Rust では、DeveloperToolsCredentialをローカルで使用し、AzureでManagedIdentityCredentialします。
どのように機能するのか
Microsoft Foundry の OpenAI 互換エンドポイント (https://<resource-name>.openai.azure.com/openai/v1/) は、静的 API キーの代わりにMicrosoft Entra IDからベアラー トークンを受け入れます。 このガイドでは、GitHub Copilot SDK ランタイムが必要に応じて新しいトークンを要求できるように、トークン プロバイダーのコールバックを使用します。
Pythonを例として使用すると、フローは次のようになります。
- お使いの環境に合わせて
DefaultAzureCredentialを構成します。 DefaultAzureCredentialを使用してhttps://ai.azure.com/.defaultスコープのトークンを取得するコールバックを、BYOK プロバイダー構成のbearer_token_providerに渡します。- GitHub Copilot SDK は、そのコールバックを介してオンデマンドで新しいトークンを要求できるようにします。

コードサンプル
Prerequisites
言語のAzure ID パッケージと GitHub Copilot SDK パッケージをインストールします。
dotnet add package GitHub.Copilot.SDK
dotnet add package Azure.Core
go get github.com/github/copilot-sdk/go
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>
<version>${copilot.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>${azure.identity.version}</version>
</dependency>
pip install github-copilot-sdk azure-identity
cargo add github-copilot-sdk azure_identity azure_core
cargo add tokio --features macros,rt-multi-thread
npm install @github/copilot-sdk @azure/identity
トークン プロバイダーコールバックを使用する
この方法は、GitHub Copilot SDK ランタイムが、指定したコールバックを介してオンデマンドで新しいトークンを要求する場合に使用します。 Azure Identity SDK は、トークンのキャッシュと更新のタイミングを処理します。
言語固有の実装を次に示します。
using Azure.Core;
using Azure.Identity;
using GitHub.Copilot;
DefaultAzureCredential credential = new(
DefaultAzureCredential.DefaultEnvironmentVariableName);
await using CopilotClient client = new();
string foundryUrl = Environment.GetEnvironmentVariable("FOUNDRY_RESOURCE_URL")!;
await using CopilotSession session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-5.5",
Provider = new ProviderConfig
{
Type = "openai",
BaseUrl = $"{foundryUrl}/openai/v1/",
BearerTokenProvider = async _ =>
{
AccessToken token = await credential.GetTokenAsync(
new TokenRequestContext(["https://ai.azure.com/.default"]));
return token.Token;
},
WireApi = "responses",
},
});
AssistantMessageEvent? response = await session.SendAndWaitAsync(
new MessageOptions { Prompt = "Hello from Managed Identity!" });
Console.WriteLine(response?.Data.Content);
package main
import (
"context"
"fmt"
"log"
"os"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
copilot "github.com/github/copilot-sdk/go"
)
func main() {
opts := azidentity.DefaultAzureCredentialOptions{RequireAzureTokenCredentials: true}
credential, err := azidentity.NewDefaultAzureCredential(&opts)
if err != nil {
log.Fatal(err)
}
getBearerToken := func(args copilot.ProviderTokenArgs) (string, error) {
token, err := credential.GetToken(context.Background(), policy.TokenRequestOptions{
Scopes: []string{"https://ai.azure.com/.default"},
})
if err != nil {
return "", err
}
return token.Token, nil
}
client := copilot.NewClient(nil)
if err := client.Start(context.Background()); err != nil {
log.Fatal(err)
}
defer client.Stop()
foundryURL := os.Getenv("FOUNDRY_RESOURCE_URL")
session, err := client.CreateSession(context.Background(), &copilot.SessionConfig{
Model: "gpt-5.5",
Provider: &copilot.ProviderConfig{
Type: "openai",
BaseURL: fmt.Sprintf("%s/openai/v1/", foundryURL),
BearerTokenProvider: getBearerToken,
WireAPI: "responses",
},
})
if err != nil {
log.Fatal(err)
}
defer session.Disconnect()
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
response, err := session.SendAndWait(ctx, copilot.MessageOptions{
Prompt: "Hello from Managed Identity!",
})
if err != nil {
log.Fatal(err)
}
if response != nil {
if data, ok := response.Data.(*copilot.AssistantMessageData); ok {
fmt.Println(data.Content)
}
}
}
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.github.copilot.CopilotClient;
import com.github.copilot.generated.AssistantMessageEvent;
import com.github.copilot.rpc.BearerTokenProvider;
import com.github.copilot.rpc.MessageOptions;
import com.github.copilot.rpc.ProviderConfig;
import com.github.copilot.rpc.SessionConfig;
public class ManagedIdentityExample {
public static void main(String[] args) throws Exception {
var credential = new DefaultAzureCredentialBuilder()
.requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
.build();
BearerTokenProvider tokenProvider = providerArgs ->
credential
.getToken(new TokenRequestContext().addScopes("https://ai.azure.com/.default"))
.map(accessToken -> accessToken.getToken())
.toFuture();
String foundryUrl = System.getenv("FOUNDRY_RESOURCE_URL");
try (var client = new CopilotClient()) {
client.start().get();
var session = client.createSession(new SessionConfig()
.setModel("gpt-5.5")
.setProvider(new ProviderConfig()
.setType("openai")
.setBaseUrl(foundryUrl + "/openai/v1/")
.setBearerTokenProvider(tokenProvider)
.setWireApi("responses")))
.get();
AssistantMessageEvent response = session
.sendAndWait(new MessageOptions().setPrompt("Hello from Managed Identity!"))
.get();
System.out.println(response.getData().content());
session.disconnect().get();
}
}
}
import asyncio
import os
from azure.identity.aio import DefaultAzureCredential
from copilot import CopilotClient
from copilot.session import PermissionHandler, ProviderConfig
async def main():
credential = DefaultAzureCredential(require_envvar=True)
async def get_bearer_token(_args) -> str:
token = await credential.get_token("https://ai.azure.com/.default")
return token.token
foundry_url = os.environ["FOUNDRY_RESOURCE_URL"]
client = CopilotClient()
await client.start()
session = await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="gpt-5.5",
provider=ProviderConfig(
type="openai",
base_url=f"{foundry_url.rstrip('/')}/openai/v1/",
bearer_token_provider=get_bearer_token,
wire_api="responses",
),
)
response = await session.send_and_wait("Hello from Managed Identity!")
print(response.data.content)
await client.stop()
await credential.close()
asyncio.run(main())
use std::sync::Arc;
use azure_core::credentials::TokenCredential;
use azure_identity::{DeveloperToolsCredential, ManagedIdentityCredential};
use github_copilot_sdk::{BearerTokenError, Client, ClientOptions, MessageOptions, ProviderTokenArgs};
use github_copilot_sdk::types::{ProviderConfig, SessionConfig};
fn credential_for_environment() -> azure_core::Result<Arc<dyn TokenCredential>> {
match std::env::var("AZURE_TOKEN_CREDENTIALS").as_deref() {
Ok("ManagedIdentityCredential") => Ok(ManagedIdentityCredential::new(None)?),
_ => Ok(DeveloperToolsCredential::new(None)?),
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let credential = credential_for_environment()?;
let foundry_url = std::env::var("FOUNDRY_RESOURCE_URL")?;
let get_bearer_token = {
let credential = credential.clone();
move |_args: ProviderTokenArgs| {
let credential = credential.clone();
async move {
let token = credential
.get_token(&["https://ai.azure.com/.default"], None)
.await
.map_err(|err| BearerTokenError::message(err.to_string()))?;
Ok(token.token.secret().to_string())
}
}
};
let mut provider = ProviderConfig::default();
provider.provider_type = Some("openai".to_string());
provider.base_url = format!("{}/openai/v1/", foundry_url.trim_end_matches('/'));
provider.bearer_token_provider = Some(Arc::new(get_bearer_token));
provider.wire_api = Some("responses".to_string());
let mut config = SessionConfig::default();
config.model = Some("gpt-5.5".to_string());
config.provider = Some(provider);
let client = Client::start(ClientOptions::default()).await?;
let session = client.create_session(config).await?;
session
.send_and_wait(MessageOptions::new("Hello from Managed Identity!"))
.await?;
session.disconnect().await?;
client.stop().await?;
Ok(())
}
import { DefaultAzureCredential } from "@azure/identity";
import { CopilotClient } from "@github/copilot-sdk";
const credential = new DefaultAzureCredential({
requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"],
});
const getBearerToken = async () => {
const tokenResponse = await credential.getToken("https://ai.azure.com/.default");
return tokenResponse.token;
};
const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5.5",
provider: {
type: "openai",
baseUrl: `${process.env.FOUNDRY_RESOURCE_URL}/openai/v1/`,
bearerTokenProvider: getBearerToken,
wireApi: "responses",
},
});
const response = await session.sendAndWait({ prompt: "Hello from Managed Identity!" });
console.log(response?.data.content);
await client.stop();
環境構成
| 変数 | Description | Example |
|---|---|---|
AZURE_TOKEN_CREDENTIALS | ||
Azureで実行する場合は、Managedに設定します。 | ||
ローカルで実行する場合は、devまたは開発者ツールの資格情報名 (Azure など) に設定します。 | Managed | |
AZURE_CLIENT_ID | ||
| 省略可。 | ||
Azureで実行する場合は、Managedを使用するときに、ユーザー割り当てマネージド ID のクライアント ID に設定します。 設定されていない場合、Azureはシステム割り当てマネージド ID を使用します。 | 11111111-2222-3333-4444-555555555555 | |
FOUNDRY_RESOURCE_ | Microsoft Foundry リソースの URL | https:/ |
API キー環境変数は必要ありません。認証はAzure ID 資格情報によって処理されます。 .NET、Go、Java、Python、TypeScript では、DefaultAzureCredentialは自動的に次をサポートします。
- マネージド ID (システム割り当てまたはユーザー割り当て): Azureホストされているアプリの場合
- Azure CLI (
az login): ローカル開発用 - 環境変数(
AZURE_CLIENT_ID、AZURE_TENANT_ID、AZURE_CLIENT_SECRET): サービス プリンシパル用 - ワークロード アイデンティティ: Kubernetes 向け
.NET、Go、Java、Python、TypeScript では、ManagedIdentityCredential は、ユーザー割り当てマネージド ID を選択するために AZURE_CLIENT_ID を読み取ります。 Rust は、このガイドでは例外です。
Rust では、ローカル開発には DeveloperToolsCredential を使用し、Azure で実行する場合は ManagedIdentityCredential を使用します。 その他の言語については、完全な資格情報チェーンの DefaultAzureCredential ドキュメントを参照してください。
このパターンを使用する場合
| シナリオ | レコメンデーション |
|---|---|
| マネージド ID を使用した Azure でホストされるアプリ | |
| ✅ このパターンを使用する | |
| 既存のMicrosoft Entra サービス プリンシパルを持つアプリ | |
| ✅ このパターンを使用する | |
az login を使用したローカル開発 | |
| ✅ このパターンを使用する | |
| 静的 API キーを使用する Azure 以外の環境 | |
| AUTOTITLE を使用する | |
| 利用可能なGitHub Copilot サブスクリプション | |
| AUTOTITLE を使用する |
こちらも参照ください
- BYOK (独自のキーを持ち込む): 静的 API キーの構成
- バックエンド サービスのセットアップ: サーバー側の展開