Login to Azure SQL with JWT token in python – [SQL Server]Login failed for user ‘
I try to connect to Azure SQL using SQLAlchemy in python, authenticating with JWT generated for App registration. Despite checking almost any combination of parameters and granting all potentially meaningful permissions, I still get following error:
[28000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Login failed for user ”. (18456)
I did the following:
- Created App registration ‘test-app’.
- Executed on the db:
CREATE USER [test-app] FROM EXTERNAL PROVIDER;
EXEC sp_addrolemember N'db_datareader', N'test-app';
GRANT SELECT ON test_vw to [test-app];
- Added ‘test-app’ to Contributor and Reader roles for the SQL Server.
- Whitelisted IP in the portal – I’m able to log in through SSMS and ‘AAD Universal with MFA’ using personal account.
- Generated token with (tenant ID matches the one used by the organization):
POST login.microsoftonline.com/9ff8761-1be4-4729-b88df-e421e19d92f/oauth2/v2.0/token HTTP/1.1
Content-Type: application/x-www-form-urlencodedclient_id=[client_id]
client_secret=[client_secret]
scope=https://database.windows.net/.default
grant_type=client_credentials
- Used generated JWT token in following python code:
from sqlalchemy import create_engine
import urllib
import struct
server = "test-server.database.windows.net"
database = "test-db"
driver = "{ODBC Driver 17 for SQL Server}"
jwt_token = "<jwt_token>"
SQL_COPT_SS_ACCESS_TOKEN = 1256
exptoken = b""
for i in bytes(jwt_token, "UTF-8"):
exptoken += bytes({i})
exptoken += bytes(1)
tokenstruct = struct.pack("=i", len(exptoken)) + exptoken
params = urllib.parse.quote_plus(
f"Driver={driver};Server={server};Database={database};Encrypt=yes"
)
conn_str = f"mssql+pyodbc:///?odbc_connect={params}"
engine_azure = create_engine(
conn_str,
connect_args={"attrs_before": {SQL_COPT_SS_ACCESS_TOKEN: tokenstruct}},
echo=True,
)
with engine_azure.connect() as con:
rs = con.execute("SELECT TOP 100 * FROM test_vw")
for row in rs:
print(row)
Any idea what I’ve missed?
Read more here: Source link