MIGRATION.md

  1# Migrating from autorest/adal to azidentity
  2
  3`azidentity` provides Microsoft Entra ID ([formerly Azure Active Directory](https://learn.microsoft.com/entra/fundamentals/new-name)) authentication for the newest Azure SDK modules (`github.com/azure-sdk-for-go/sdk/...`). Older Azure SDK packages (`github.com/azure-sdk-for-go/services/...`) use types from `github.com/go-autorest/autorest/adal` instead.
  4
  5This guide shows common authentication code using `autorest/adal` and its equivalent using `azidentity`.
  6
  7## Table of contents
  8
  9- [Acquire a token](#acquire-a-token)
 10- [Client certificate authentication](#client-certificate-authentication)
 11- [Client secret authentication](#client-secret-authentication)
 12- [Configuration](#configuration)
 13- [Device code authentication](#device-code-authentication)
 14- [Managed identity](#managed-identity)
 15- [Use azidentity credentials with older packages](#use-azidentity-credentials-with-older-packages)
 16
 17## Configuration
 18
 19### `autorest/adal`
 20
 21Token providers require a token audience (resource identifier) and an instance of `adal.OAuthConfig`, which requires a Microsoft Entra endpoint and tenant:
 22
 23```go
 24import "github.com/Azure/go-autorest/autorest/adal"
 25
 26oauthCfg, err := adal.NewOAuthConfig("https://login.chinacloudapi.cn", tenantID)
 27handle(err)
 28
 29spt, err := adal.NewServicePrincipalTokenWithSecret(
 30    *oauthCfg, clientID, "https://management.chinacloudapi.cn/", &adal.ServicePrincipalTokenSecret{ClientSecret: secret},
 31)
 32```
 33
 34### `azidentity`
 35
 36A credential instance can acquire tokens for any audience. The audience for each token is determined by the client requesting it. Credentials require endpoint configuration only for sovereign or private clouds. The `azcore/cloud` package has predefined configuration for sovereign clouds such as Azure China:
 37
 38```go
 39import (
 40    "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
 41    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
 42)
 43
 44clientOpts := azcore.ClientOptions{Cloud: cloud.AzureChina}
 45
 46cred, err := azidentity.NewClientSecretCredential(
 47    tenantID, clientID, secret, &azidentity.ClientSecretCredentialOptions{ClientOptions: clientOpts},
 48)
 49handle(err)
 50```
 51
 52## Client secret authentication
 53
 54### `autorest/adal`
 55
 56```go
 57import (
 58    "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
 59    "github.com/Azure/go-autorest/autorest"
 60    "github.com/Azure/go-autorest/autorest/adal"
 61)
 62
 63oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
 64handle(err)
 65spt, err := adal.NewServicePrincipalTokenWithSecret(
 66    *oauthCfg, clientID, "https://management.azure.com/", &adal.ServicePrincipalTokenSecret{ClientSecret: secret},
 67)
 68handle(err)
 69
 70client := subscriptions.NewClient()
 71client.Authorizer = autorest.NewBearerAuthorizer(spt)
 72```
 73
 74### `azidentity`
 75
 76```go
 77import (
 78    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
 79    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
 80)
 81
 82cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil)
 83handle(err)
 84
 85client, err := armsubscriptions.NewClient(cred, nil)
 86handle(err)
 87```
 88
 89## Client certificate authentication
 90
 91### `autorest/adal`
 92
 93```go
 94import (
 95    "os"
 96
 97    "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
 98    "github.com/Azure/go-autorest/autorest"
 99    "github.com/Azure/go-autorest/autorest/adal"
100)
101certData, err := os.ReadFile("./example.pfx")
102handle(err)
103
104certificate, rsaPrivateKey, err := decodePkcs12(certData, "")
105handle(err)
106
107oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
108handle(err)
109
110spt, err := adal.NewServicePrincipalTokenFromCertificate(
111    *oauthConfig, clientID, certificate, rsaPrivateKey, "https://management.azure.com/",
112)
113
114client := subscriptions.NewClient()
115client.Authorizer = autorest.NewBearerAuthorizer(spt)
116```
117
118### `azidentity`
119
120```go
121import (
122    "os"
123
124    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
125    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
126)
127
128certData, err := os.ReadFile("./example.pfx")
129handle(err)
130
131certs, key, err := azidentity.ParseCertificates(certData, nil)
132handle(err)
133
134cred, err = azidentity.NewClientCertificateCredential(tenantID, clientID, certs, key, nil)
135handle(err)
136
137client, err := armsubscriptions.NewClient(cred, nil)
138handle(err)
139```
140
141## Managed identity
142
143### `autorest/adal`
144
145```go
146import (
147    "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
148    "github.com/Azure/go-autorest/autorest"
149    "github.com/Azure/go-autorest/autorest/adal"
150)
151
152spt, err := adal.NewServicePrincipalTokenFromManagedIdentity("https://management.azure.com/", nil)
153handle(err)
154
155client := subscriptions.NewClient()
156client.Authorizer = autorest.NewBearerAuthorizer(spt)
157```
158
159### `azidentity`
160
161```go
162import (
163    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
164    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
165)
166
167cred, err := azidentity.NewManagedIdentityCredential(nil)
168handle(err)
169
170client, err := armsubscriptions.NewClient(cred, nil)
171handle(err)
172```
173
174### User-assigned identities
175
176`autorest/adal`:
177
178```go
179import "github.com/Azure/go-autorest/autorest/adal"
180
181opts := &adal.ManagedIdentityOptions{ClientID: "..."}
182spt, err := adal.NewServicePrincipalTokenFromManagedIdentity("https://management.azure.com/")
183handle(err)
184```
185
186`azidentity`:
187
188```go
189import "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
190
191opts := azidentity.ManagedIdentityCredentialOptions{ID: azidentity.ClientID("...")}
192cred, err := azidentity.NewManagedIdentityCredential(&opts)
193handle(err)
194```
195
196## Device code authentication
197
198### `autorest/adal`
199
200```go
201import (
202    "fmt"
203    "net/http"
204
205    "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
206    "github.com/Azure/go-autorest/autorest"
207    "github.com/Azure/go-autorest/autorest/adal"
208)
209
210oauthClient := &http.Client{}
211oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
212handle(err)
213resource := "https://management.azure.com/"
214deviceCode, err := adal.InitiateDeviceAuth(oauthClient, *oauthCfg, clientID, resource)
215handle(err)
216
217// display instructions, wait for the user to authenticate
218fmt.Println(*deviceCode.Message)
219token, err := adal.WaitForUserCompletion(oauthClient, deviceCode)
220handle(err)
221
222spt, err := adal.NewServicePrincipalTokenFromManualToken(*oauthCfg, clientID, resource, *token)
223handle(err)
224
225client := subscriptions.NewClient()
226client.Authorizer = autorest.NewBearerAuthorizer(spt)
227```
228
229### `azidentity`
230
231```go
232import (
233    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
234    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions"
235)
236
237cred, err := azidentity.NewDeviceCodeCredential(nil)
238handle(err)
239
240client, err := armsubscriptions.NewSubscriptionsClient(cred, nil)
241handle(err)
242```
243
244`azidentity.DeviceCodeCredential` will guide a user through authentication, printing instructions to the console by default. The user prompt is customizable. For more information, see the [package documentation](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#DeviceCodeCredential).
245
246## Acquire a token
247
248### `autorest/adal`
249
250```go
251import "github.com/Azure/go-autorest/autorest/adal"
252
253oauthCfg, err := adal.NewOAuthConfig("https://login.microsoftonline.com", tenantID)
254handle(err)
255
256spt, err := adal.NewServicePrincipalTokenWithSecret(
257    *oauthCfg, clientID, "https://vault.azure.net", &adal.ServicePrincipalTokenSecret{ClientSecret: secret},
258)
259
260err = spt.Refresh()
261if err == nil {
262    token := spt.Token
263}
264```
265
266### `azidentity`
267
268In ordinary usage, application code doesn't need to request tokens from credentials directly. Azure SDK clients handle token acquisition and refreshing internally. However, applications may call `GetToken()` to do so. All credential types have this method.
269
270```go
271import (
272    "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
273    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
274)
275
276cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil)
277handle(err)
278
279tk, err := cred.GetToken(
280    context.TODO(), policy.TokenRequestOptions{Scopes: []string{"https://vault.azure.net/.default"}},
281)
282if err == nil {
283    token := tk.Token
284}
285```
286
287Note that `azidentity` credentials use the Microsoft Entra endpoint, which requires OAuth 2 scopes instead of the resource identifiers `autorest/adal` expects. For more information, see [Microsoft Entra ID documentation](https://learn.microsoft.com/entra/identity-platform/permissions-consent-overview).
288
289## Use azidentity credentials with older packages
290
291The [azidext module](https://pkg.go.dev/github.com/jongio/azidext/go/azidext) provides an adapter for `azidentity` credential types. The adapter enables using the credential types with older Azure SDK clients. For example:
292
293```go
294import (
295    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
296    "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-06-01/subscriptions"
297    "github.com/jongio/azidext/go/azidext"
298)
299
300cred, err := azidentity.NewClientSecretCredential(tenantID, clientID, secret, nil)
301handle(err)
302
303client := subscriptions.NewClient()
304client.Authorizer = azidext.NewTokenCredentialAdapter(cred, []string{"https://management.azure.com//.default"})
305```
306
307![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-go%2Fsdk%2Fazidentity%2FMIGRATION.png)