interactive_browser_credential.go

  1//go:build go1.18
  2// +build go1.18
  3
  4// Copyright (c) Microsoft Corporation. All rights reserved.
  5// Licensed under the MIT License.
  6
  7package azidentity
  8
  9import (
 10	"context"
 11
 12	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
 13	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
 14	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
 15)
 16
 17const credNameBrowser = "InteractiveBrowserCredential"
 18
 19// InteractiveBrowserCredentialOptions contains optional parameters for InteractiveBrowserCredential.
 20type InteractiveBrowserCredentialOptions struct {
 21	azcore.ClientOptions
 22
 23	// AdditionallyAllowedTenants specifies additional tenants for which the credential may acquire
 24	// tokens. Add the wildcard value "*" to allow the credential to acquire tokens for any tenant.
 25	AdditionallyAllowedTenants []string
 26
 27	// authenticationRecord returned by a call to a credential's Authenticate method. Set this option
 28	// to enable the credential to use data from a previous authentication.
 29	authenticationRecord authenticationRecord
 30
 31	// ClientID is the ID of the application users will authenticate to.
 32	// Defaults to the ID of an Azure development application.
 33	ClientID string
 34
 35	// disableAutomaticAuthentication prevents the credential from automatically prompting the user to authenticate.
 36	// When this option is true, GetToken will return authenticationRequiredError when user interaction is necessary
 37	// to acquire a token.
 38	disableAutomaticAuthentication bool
 39
 40	// DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or
 41	// private clouds such as Azure Stack. It determines whether the credential requests Microsoft Entra instance metadata
 42	// from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making
 43	// the application responsible for ensuring the configured authority is valid and trustworthy.
 44	DisableInstanceDiscovery bool
 45
 46	// LoginHint pre-populates the account prompt with a username. Users may choose to authenticate a different account.
 47	LoginHint string
 48
 49	// RedirectURL is the URL Microsoft Entra ID will redirect to with the access token. This is required
 50	// only when setting ClientID, and must match a redirect URI in the application's registration.
 51	// Applications which have registered "http://localhost" as a redirect URI need not set this option.
 52	RedirectURL string
 53
 54	// TenantID is the Microsoft Entra tenant the credential authenticates in. Defaults to the
 55	// "organizations" tenant, which can authenticate work and school accounts.
 56	TenantID string
 57
 58	// tokenCachePersistenceOptions enables persistent token caching when not nil.
 59	tokenCachePersistenceOptions *tokenCachePersistenceOptions
 60}
 61
 62func (o *InteractiveBrowserCredentialOptions) init() {
 63	if o.TenantID == "" {
 64		o.TenantID = organizationsTenantID
 65	}
 66	if o.ClientID == "" {
 67		o.ClientID = developerSignOnClientID
 68	}
 69}
 70
 71// InteractiveBrowserCredential opens a browser to interactively authenticate a user.
 72type InteractiveBrowserCredential struct {
 73	client *publicClient
 74}
 75
 76// NewInteractiveBrowserCredential constructs a new InteractiveBrowserCredential. Pass nil to accept default options.
 77func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOptions) (*InteractiveBrowserCredential, error) {
 78	cp := InteractiveBrowserCredentialOptions{}
 79	if options != nil {
 80		cp = *options
 81	}
 82	cp.init()
 83	msalOpts := publicClientOptions{
 84		AdditionallyAllowedTenants:     cp.AdditionallyAllowedTenants,
 85		ClientOptions:                  cp.ClientOptions,
 86		DisableAutomaticAuthentication: cp.disableAutomaticAuthentication,
 87		DisableInstanceDiscovery:       cp.DisableInstanceDiscovery,
 88		LoginHint:                      cp.LoginHint,
 89		Record:                         cp.authenticationRecord,
 90		RedirectURL:                    cp.RedirectURL,
 91		TokenCachePersistenceOptions:   cp.tokenCachePersistenceOptions,
 92	}
 93	c, err := newPublicClient(cp.TenantID, cp.ClientID, credNameBrowser, msalOpts)
 94	if err != nil {
 95		return nil, err
 96	}
 97	return &InteractiveBrowserCredential{client: c}, nil
 98}
 99
100// Authenticate a user via the default browser. Subsequent calls to GetToken will automatically use the returned AuthenticationRecord.
101func (c *InteractiveBrowserCredential) authenticate(ctx context.Context, opts *policy.TokenRequestOptions) (authenticationRecord, error) {
102	var err error
103	ctx, endSpan := runtime.StartSpan(ctx, credNameBrowser+"."+traceOpAuthenticate, c.client.azClient.Tracer(), nil)
104	defer func() { endSpan(err) }()
105	tk, err := c.client.Authenticate(ctx, opts)
106	return tk, err
107}
108
109// GetToken requests an access token from Microsoft Entra ID. This method is called automatically by Azure SDK clients.
110func (c *InteractiveBrowserCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) {
111	var err error
112	ctx, endSpan := runtime.StartSpan(ctx, credNameBrowser+"."+traceOpGetToken, c.client.azClient.Tracer(), nil)
113	defer func() { endSpan(err) }()
114	tk, err := c.client.GetToken(ctx, opts)
115	return tk, err
116}
117
118var _ azcore.TokenCredential = (*InteractiveBrowserCredential)(nil)