func AuthenticateDeviceFlow(env azure.Environment, subscriptionID string) (*azure.ServicePrincipalToken, error) {
	// First we locate the tenant ID of the subscription as we store tokens per
	// tenant (which could have multiple subscriptions)
	tenantID, err := loadOrFindTenantID(env, subscriptionID)
	if err != nil {
		return nil, err
	}
	oauthCfg, err := env.OAuthConfigForTenant(tenantID)
	if err != nil {
		return nil, fmt.Errorf("Failed to obtain oauth config for azure environment: %v", err)
	}

	tokenPath := tokenCachePath(tenantID)
	saveToken := mkTokenCallback(tokenPath)
	saveTokenCallback := func(t azure.Token) error {
		log.Debug("Azure token expired. Saving the refreshed token...")
		return saveToken(t)
	}
	f := logutil.Fields{"path": tokenPath}

	appID, ok := appIDs[env.Name]
	if !ok {
		return nil, fmt.Errorf("docker-machine application not set up for Azure environment %q", env.Name)
	}
	scope := getScope(env)

	// Lookup the token cache file for an existing token.
	spt, err := tokenFromFile(*oauthCfg, tokenPath, appID, scope, saveTokenCallback)
	if err != nil {
		return nil, err
	}
	if spt != nil {
		log.Debug("Auth token found in file.", f)

		// NOTE(ahmetalpbalkan): The token file we found might be containing an
		// expired access_token. In that case, the first call to Azure SDK will
		// attempt to refresh the token using refresh_token –which might have
		// expired[1], in that case we will get an error and we shall remove the
		// token file and initiate token flow again so that the user would not
		// need removing the token cache file manually.
		//
		// [1]: for device flow auth, the expiration date of refresh_token is
		//      not returned in AAD /token response, we just know it is 14
		//      days. Therefore user’s token will go stale every 14 days and we
		//      will delete the token file, re-initiate the device flow. Service
		//      Principal Account tokens are not subject to this limitation.
		log.Debug("Validating the token.")
		if err := validateToken(env, spt); err != nil {
			log.Debug(fmt.Sprintf("Error: %v", err))
			log.Debug(fmt.Sprintf("Deleting %s", tokenPath))
			if err := os.RemoveAll(tokenPath); err != nil {
				return nil, fmt.Errorf("Error deleting stale token file: %v", err)
			}
		} else {
			log.Debug("Token works.")
			return spt, nil
		}
	}

	log.Debug("Obtaining a token.", f)
	spt, err = deviceFlowAuth(*oauthCfg, appID, scope)
	if err != nil {
		return nil, err
	}
	log.Debug("Obtained a token.")
	if err := saveToken(spt.Token); err != nil {
		log.Error("Error occurred saving token to cache file.")
		return nil, err
	}
	return spt, nil
}
func AuthenticateDeviceFlow(env azure.Environment, subscriptionID string) (*azure.ServicePrincipalToken, error) {
	
	
	tenantID, err := loadOrFindTenantID(env, subscriptionID)
	if err != nil {
		return nil, err
	}
	oauthCfg, err := env.OAuthConfigForTenant(tenantID)
	if err != nil {
		return nil, fmt.Errorf("Failed to obtain oauth config for azure environment: %v", err)
	}

	tokenPath := tokenCachePath(tenantID)
	saveToken := mkTokenCallback(tokenPath)
	saveTokenCallback := func(t azure.Token) error {
		log.Debug("Azure token expired. Saving the refreshed token...")
		return saveToken(t)
	}
	f := logutil.Fields{"path": tokenPath}

	appID, ok := appIDs[env.Name]
	if !ok {
		return nil, fmt.Errorf("docker-machine application not set up for Azure environment %q", env.Name)
	}
	scope := getScope(env)

	
	spt, err := tokenFromFile(*oauthCfg, tokenPath, appID, scope, saveTokenCallback)
	if err != nil {
		return nil, err
	}
	if spt != nil {
		log.Debug("Auth token found in file.", f)

		
		
		
		
		
		
		
		
		
		
		
		
		log.Debug("Validating the token.")
		if err := validateToken(env, spt); err != nil {
			log.Debug(fmt.Sprintf("Error: %v", err))
			log.Debug(fmt.Sprintf("Deleting %s", tokenPath))
			if err := os.RemoveAll(tokenPath); err != nil {
				return nil, fmt.Errorf("Error deleting stale token file: %v", err)
			}
		} else {
			log.Debug("Token works.")
			return spt, nil
		}
	}

	log.Debug("Obtaining a token.", f)
	spt, err = deviceFlowAuth(*oauthCfg, appID, scope)
	if err != nil {
		return nil, err
	}
	log.Debug("Obtained a token.")
	if err := saveToken(spt.Token); err != nil {
		log.Error("Error occurred saving token to cache file.")
		return nil, err
	}
	return spt, nil
}
func AuthenticateDeviceFlow ( env azure . Environment , subscriptionID string ) ( * azure . ServicePrincipalToken , error ) { // First we locate the tenant ID of the subscription as we store tokens per // tenant (which could have multiple subscriptions) tenantID , err := loadOrFindTenantID ( env , subscriptionID ) if err != nil { return nil , err } oauthCfg , err := env . OAuthConfigForTenant ( tenantID ) if err != nil { return nil , fmt . Errorf ( " " , err ) } tokenPath := tokenCachePath ( tenantID ) saveToken := mkTokenCallback ( tokenPath ) saveTokenCallback := func ( t azure . Token ) error { log . Debug ( " " ) return saveToken ( t ) } f := logutil . Fields { " " : tokenPath } appID , ok := appIDs [ env . Name ] if ! ok { return nil , fmt . Errorf ( " " , env . Name ) } scope := getScope ( env ) // Lookup the token cache file for an existing token. spt , err := tokenFromFile ( * oauthCfg , tokenPath , appID , scope , saveTokenCallback ) if err != nil { return nil , err } if spt != nil { log . Debug ( " " , f ) // NOTE(ahmetalpbalkan): The token file we found might be containing an // expired access_token. In that case, the first call to Azure SDK will // attempt to refresh the token using refresh_token –which might have // expired[1], in that case we will get an error and we shall remove the // token file and initiate token flow again so that the user would not // need removing the token cache file manually. // // [1]: for device flow auth, the expiration date of refresh_token is //      not returned in AAD /token response, we just know it is 14 //      days. Therefore user’s token will go stale every 14 days and we //      will delete the token file, re-initiate the device flow. Service //      Principal Account tokens are not subject to this limitation. log . Debug ( " " ) if err := validateToken ( env , spt ) ; err != nil { log . Debug ( fmt . Sprintf ( " " , err ) ) log . Debug ( fmt . Sprintf ( " " , tokenPath ) ) if err := os . RemoveAll ( tokenPath ) ; err != nil { return nil , fmt . Errorf ( " " , err ) } } else { log . Debug ( " " ) return spt , nil } } log . Debug ( " " , f ) spt , err = deviceFlowAuth ( * oauthCfg , appID , scope ) if err != nil { return nil , err } log . Debug ( " " ) if err := saveToken ( spt . Token ) ; err != nil { log . Error ( " " ) return nil , err } return spt , nil }
// AuthenticateDeviceFlow fetches a token from the local file cache or initiates a consent
// flow and waits for token to be obtained. Obtained token is stored in a file cache for
// future use and refreshing.
AuthenticateDeviceFlow fetches a token from the local file cache or initiates a consent flow and waits for token to be obtained . Obtained token is stored in a file cache for future use and refreshing .