denisenkom / go-mssqldb

Microsoft SQL server driver written in go language
BSD 3-Clause "New" or "Revised" License
1.82k stars 497 forks source link

Azure AD authentication / TLS issue #644

Open nikos06 opened 3 years ago

nikos06 commented 3 years ago

Hi ! I'm trying to authenticate to a remote sql server using azure AD authentication without any success. I am stuck with a a cryptic error : TLS Handshake failed: unexpected packet 4, expecting prelogin

Here is the simple program i used :

package main

import (
    "database/sql"
    "fmt"
    mssql "github.com/denisenkom/go-mssqldb"
    "log"
)

const server = "XXX.crm4.dynamics.com"
const database = "mydb"
const token = "XXXXXXXX"

func getTokenProvider() (func() (string, error), error) {
    return func() (string, error) {
        return token, nil
    }, nil
}

func main() {
    connString := fmt.Sprintf("Server=%s;Database=%s;", server, database)
    fmt.Printf("connString:%s\n", connString)

    tokenProvider, err := getTokenProvider()
    if err != nil {
        log.Fatal("Error creating token provider :", err)
    }

    connector, err := mssql.NewAccessTokenConnector(
        connString, tokenProvider)
    if err != nil {
        log.Fatal("Connector creation failed:", err)
    }
    conn := sql.OpenDB(connector)
    defer conn.Close()

    row := conn.QueryRow("select 1, 'abc'")
    var somenumber int64
    var somechars string
    err = row.Scan(&somenumber, &somechars)
    if err != nil {
        log.Fatal("Scan failed:", err)
    }
    fmt.Printf("somenumber:%d\n", somenumber)
    fmt.Printf("somechars:%s\n", somechars)

    fmt.Printf("bye\n")
}

Code is using master branch, not v0.9.0 tag and therefore contains https://github.com/denisenkom/go-mssqldb/pull/546

sqlcmd -S XXXX.crm4.dynamics.com -d mydb -G -U USER@YYYY.onmicrosoft.com -P PASSWORD is working just fine.

I wanted to test access to the DB using an access token but never got a chance to do it as the code fails in tds.go, line 1117 : err = tlsConn.Handshake() So, it never reaches line 1137 : login, err := prepareLogin(ctx, c, p, log, auth, fedAuth, uint32(outbuf.PackageSize())) to prepare login based on the access token.

I must be missing something but I don't know what. The only difference from what I've read so far is that I'm trying to connect to an SQL server instance running for Dynamics 365. Any help would be appreciated (@wrosenuance, @paulmey ?) !