Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Join us at FabCon Vienna from September 15-18, 2025, for the ultimate Fabric, Power BI, SQL, and AI community-led learning event. Save €200 with code FABCOMM. Get registered

Reply
zas3112
New Member

Warehouse external connectivity via Service Principal

Hello everyone,
I am trying to connect with warehouse using service prinicpal to share my data externally.

 

Steps I have performed:
1- Created a service principal on Azure

2- Added service principal to Workspace as Admin (Workspace which containes warehouse which I want to share externally)

3- Created secret key for the application (service principal) 

 

Error I am facing: 

InterfaceError: ('28000', '[28000] [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Could not login because the authentication failed. (18456) (SQLDriverConnect)')

My code: 

import pyodbc
import msal
import struct

# Function to get an AAD token using MSAL (Microsoft Authentication Library)
def get_aad_token(client_id, client_secret, tenant_id😞
    authority = f"https://login.microsoftonline.com/{tenant_id}"
    app = msal.ConfidentialClientApplication(client_id, authority=authority, client_credential=client_secret)
    result = app.acquire_token_for_client(scopes=["https://analysis.windows.net/powerbi/api/.default"])
   
    if "access_token" in result:
        return result["access_token"]
    else:
        raise Exception("Error fetching token: " + str(result.get("error_description")))

# Function to return a pyodbc connection, given a connection string and using the AAD token
def create_connection(connection_string: str, token: str😞
    token_struct = struct.pack(f'<I{len(token)}s', len(token), token.encode('UTF-16-LE'))
    SQL_COPT_SS_ACCESS_TOKEN = 1256
    conn = pyodbc.connect(connection_string, attrs_before={SQL_COPT_SS_ACCESS_TOKEN: token_struct})
    return conn

# Set up your AAD authentication details
client_id = "xxx"  # Replace with your Azure AD app client ID
client_secret = "xxx"  # Replace with your Azure AD app client secret
tenant_id = "xxx"  # Replace with your Azure AD tenant ID

# Get the AAD token
token = get_aad_token(client_id, client_secret, tenant_id)

# MS Fabric SQL endpoint
sql_end_point = "xxx"
connection_string = f"Driver={{ODBC Driver 18 for SQL Server}};Server={sql_end_point};"

print(f"connection_string={connection_string}")

# Create the pyodbc connection
connection = create_connection(connection_string, token)

# Check if we can extract data (perform a simple query)
try:
    cursor = connection.cursor()
    cursor.execute("SELECT TOP 5 * from xxx")  # Replace with the actual table name
    rows = cursor.fetchall()

    # Print the fetched data
    if rows:
        for row in rows:
            print(row)
    else:
        print("No data found!")

    cursor.close()
except Exception as e:
    print(f"Error while fetching data: {e}")

# Close the connection after the query
connection.close()
1 ACCEPTED SOLUTION
MonicaCVL
Advocate I
Advocate I

Hi @zas3112 ,

Can you check if below tenant level settings are on? and have added your service principal there?

MonicaCVL_0-1747287084999.png

 

MonicaCVL_1-1747287094187.png

If you have enabled the above tenant level settings and add your service principal, then you are good to go!

I am sharing the sample code to connect to the fabric warehouse:

from sqlalchemy import create_engine
def get_engine():

    tenant_id = secret_res['tenant_id']
    service_principal_id = f"{secret_res['client_id']}@{tenant_id}"
    service_principal_secret = secret_res['client_secret']
    driver="DRIVER={{ODBC Driver 18 for SQL Server}};"

    # Define your SQL Server details
    server_name = secret_res['warehouse_conn']
    database_name = secret_res['warehouse_name']

    connection_string = (
        "mssql+pyodbc://"
        f"{server_name}/{database_name}?"
        "driver=ODBC+Driver+18+for+SQL+Server&"
        "authentication=ActiveDirectoryServicePrincipal&"
        f"user={service_principal_id}&"
        f"password={service_principal_secret}"
    )
    engine = create_engine(connection_string)
    return engine
 
 
The engine that is returned from the above function, can be used to read/write the data into warehouse,
 
engine=get_engine()
df = pd.read_sql_table(table_name, engine,schema=schema_name)
 
Hope this helps, If so please do like and accept this as solution.
 
With regards
Monica CVL
 

View solution in original post

3 REPLIES 3
zas3112
New Member

Hello @MonicaCVL 

Thankyou for the guide, this method worked

Furthermore, can you please clarify that this mode of aunthetication gives you access to all workspace items or just the warehouse? My serive principal is the admin of the workspace, if yes then can you please further guide as how can I limit service prinicpal to only warehouse

v-mdharahman
Community Support
Community Support

Hi @zas3112,

Thanks for reaching out to the Microsoft fabric community forum.

It looks like you are facing issues while connecting to your warehouse using service principle. As @MonicaCVL already responded to your query, kindly go through the response and comfirm if it solves your issue.

 

I would also take a moment to thank @MonicaCVL, for actively participating in the community forum and for the solutions you’ve been sharing in the community forum. Your contributions make a real difference.

 

If I misunderstand your needs or you still have problems on it, please feel free to let us know.  

Best Regards,
Hammad.
Community Support Team

 

If this post helps then please mark it as a solution, so that other members find it more quickly.

Thank you.

MonicaCVL
Advocate I
Advocate I

Hi @zas3112 ,

Can you check if below tenant level settings are on? and have added your service principal there?

MonicaCVL_0-1747287084999.png

 

MonicaCVL_1-1747287094187.png

If you have enabled the above tenant level settings and add your service principal, then you are good to go!

I am sharing the sample code to connect to the fabric warehouse:

from sqlalchemy import create_engine
def get_engine():

    tenant_id = secret_res['tenant_id']
    service_principal_id = f"{secret_res['client_id']}@{tenant_id}"
    service_principal_secret = secret_res['client_secret']
    driver="DRIVER={{ODBC Driver 18 for SQL Server}};"

    # Define your SQL Server details
    server_name = secret_res['warehouse_conn']
    database_name = secret_res['warehouse_name']

    connection_string = (
        "mssql+pyodbc://"
        f"{server_name}/{database_name}?"
        "driver=ODBC+Driver+18+for+SQL+Server&"
        "authentication=ActiveDirectoryServicePrincipal&"
        f"user={service_principal_id}&"
        f"password={service_principal_secret}"
    )
    engine = create_engine(connection_string)
    return engine
 
 
The engine that is returned from the above function, can be used to read/write the data into warehouse,
 
engine=get_engine()
df = pd.read_sql_table(table_name, engine,schema=schema_name)
 
Hope this helps, If so please do like and accept this as solution.
 
With regards
Monica CVL
 

Helpful resources

Announcements
May FBC25 Carousel

Fabric Monthly Update - May 2025

Check out the May 2025 Fabric update to learn about new features.

June 2025 community update carousel

Fabric Community Update - June 2025

Find out what's new and trending in the Fabric community.